You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: NEWS.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,11 +2,11 @@
2
2
3
3
#### API
4
4
- New `geom_ncdf()` function to create a `geom` for use in map composition using package `ggplot2`.
5
-
- In `CFVariable$subset()`and `$profile()`subsetting a "time" axis can now use abbreviated specification such as `time = "2025-12"` to select all data for December 2025, or `time = c("2020-S1", "2025-S4")` for all meteorological season data from 2019-12-01 to 2025-11-30 (inclusive). Abbreviation can be by month, meteorological season (S1 to S4), quarter (Q1 to Q4) or dekad (D01 to D36).
5
+
- In `CFVariable$subset()` subsetting a "time" axis can now use abbreviated specification such as `time = "2025-12"` to select all data for December 2025, or `time = c("2020-S1", "2025-S4")` for all meteorological season data from 2019-12-01 to 2025-11-30 (inclusive). Abbreviation can be by year, month, meteorological season (S1 to S4), quarter (Q1 to Q4) or dekad (D01 to D36).
6
6
7
7
#### Code
8
8
- Fixed writing attributes for groups.
9
-
- Fixed reading of scalar variables following saving of `CFDataset`.
9
+
- Fixed reading of scalar variables following subsetting of a scalar axis.
# Variables and axes can be accessed through standard list-type extraction syntax
44
-
(t2m <- ds[["t2m"]])
45
-
46
-
ds[["longitude"]]
47
-
48
-
# Regular base R operations simplify life further
49
-
dimnames(ds[["pev"]]) # A variable: list of axis names
50
-
dimnames(ds[["longitude"]]) # An axis: vector of axis coordinate values
51
-
52
-
# Access attributes
53
-
ds[["pev"]]$attribute("long_name")
54
-
```
55
-
56
-
If you just want to inspect what data is included in the netCDF resource, use the `peek_ncdf()` function:
57
-
58
-
```{r peek}
59
-
peek_ncdf(fn)
60
-
```
61
-
62
-
## Extracting data
63
-
64
-
There are various ways to read data for a data variable from the resource:
65
-
66
-
***`[]`:** The usual R array operator gives you access to the raw, non-interpreted data in the netCDF resource. This uses index values into the dimensions and requires you to know the order in which the dimensions are specified for the variable. With a bit of tinkering and some helper functions in `ncdfCF` this is still very easy to do.
67
-
***`raw()`:** This also gets the data in the layout of the file (or the data set) but with dimnames set. Importantly, you can call this after calling `subset()` and you will get the raw data for the specific spatial and temporal domain that you are interested in.
68
-
***`array()`:** Like `raw()`, this extracts all the (subsetted) data, but now the data will be oriented in the standard R way of column-major order. Y coordinates will run from the top to the bottom (so latitude values, for instance, will be decreasing).
69
-
***`subset()`:** The `subset()` method lets you specify what you want to extract from each dimension in real-world coordinates and timestamps, in whichever order. This can also rectify non-Cartesian grids to regular longitude-latitude grids. Subsetting is lazy: data is not loaded so long as a direct relationship to the data in the netCDF resource is maintained.
70
-
***`profile()`:** Extract "profiles" from the data variable. This can take different forms, such as a temporal or depth profile for a single location, but it could also be a zonal field (such as a transect in latitude - atmospheric depth for a given longitude) or some other profile in the physical space of the data variable.
71
-
72
-
```{r extract}
73
-
# Extract a timeseries for a specific location - see also the `profile()` method
74
-
ts <- t2m[5, 4, ]
75
-
str(ts)
76
-
77
-
# Extract the full spatial extent for one time step
78
-
ts <- t2m[, , 12]
79
-
str(ts)
80
38
```
81
39
82
-
Note that the results contain degenerate dimensions (of length 1). This by design when using basic `[]` data access because it allows attributes to be attached in a consistent manner. When using the `subset()` method, the data is returned as an instance of `CFVariable`, including axes and attributes:
83
-
84
-
```{r subset}
85
-
# Extract a specific region, full time dimension
86
-
(ts <- t2m$subset(list(X = 29:30, Y = -1:-2)))
87
-
88
-
# Extract specific time slices for a specific region
89
-
# Note that the dimensions are specified out of order and using alternative
90
-
# specifications: only the extreme values are used.
Data loading is lazy. In the examples above, you can see that data did not yet get loaded. This is intentional: you can subset your data in multiple ways before actually reading the data from the resource. This is particularly important when getting data from an online location, such as a remote THREDDS server. Use `raw()` or `array()` to get the arrays.
97
-
98
-
##### Make a profile of data
99
-
100
-
It is often useful to extract a "profile" of data for a given location or zone, such as a timeseries of data. The `profile()` method has some flexible options to support this:
101
-
102
-
- Profile specific locations, with multiple locations specified per call, returning the data as a (set of) `CFVariable` instance(s) or as a single `data.table`.
103
-
- Profile zones, such as a latitude band or an atmospheric level. Data is returned as a new `CFVariable` instance(s).
104
-
105
-
In all cases, you can profile over any of the axes and over any number of axes.
106
-
107
-
Note that the `profile()` method returns data for the grid cells closest to the specified location. That is different from the `subset()` method, which will return data as it is recorded in the netCDF resource.
Some critical metadata is recorded in the "value" attribute: original long name and the physical unit.
117
-
118
-
When you provide coordinates for all axes but one, you get a profile of values along the remaining axis, as shown above. If you provide fewer axis coordinates you get progressively higher-order results. To get a latitudinal transect, for instance, provide only a longitude coordinate:
Note that there is only a single longitude coordinate left, at exactly the specified longitude.
125
-
126
-
## Summarising data over time
127
-
128
-
With the `summarise()` method you can apply a function over the data to generate summaries. You could, for instance, summarise daily data to monthly means. These methods use the specific calendar of the "time" axis. The return value is a new `CFVariable` object.
129
-
130
-
```{r summarise}
131
-
# Summarising hourly temperature data to calculate the daily maximum temperature
132
-
t2m$summarise("tmax", max, "day")
133
-
```
134
-
135
-
A function may also return a vector of multiple values, in which case a list is returned with a new `CFVariable` object for each return value of the function. This allows you to calculate multiple results with a single call. You could write your own function to tailor the calculations to your needs. Rather than just calculating the daily maximum, you could get the daily maximum, minimum and diurnal range in one go:
136
-
137
-
```{r summarise_multi}
138
-
# Function to calculate multiple daily stats
139
-
# It is good practice to include a `na.rm` argument in all your functions
140
-
daily_stats <- function(x, na.rm = TRUE) {
141
-
# x is the vector of values for one day
142
-
minmax <- range(x, na.rm = na.rm)
143
-
diurnal <- minmax[2L] - minmax[1L]
144
-
c(minmax, diurnal)
145
-
}
146
-
147
-
# Call summarise() with your own function
148
-
# The `name` argument should have as many names as the function returns results
Note that you may have to update some attributes after calling `summarise()`. You can use the `set_attribute()` method on the `CFVariable` objects to do that.
153
-
154
-
## Create new netCDF objects
155
-
156
40
You can convert a suitable R object into a `CFVariable` instance quite easily. R objects that are supported include arrays, matrices and vectors of type logical, integer, numeric or logical.
157
41
158
-
```{r create_basic}
159
-
arr <- array(rnorm(120), dim = c(6, 5, 4))
160
-
as_CF("my_first_CF_object", arr)
161
-
```
162
-
163
-
Usable but not very impressive. The axes have dull names without any meaning and the coordinates are just a sequence along the axis.
164
-
165
42
If the R object has `dimnames` set, these will be used to create more informed axes. More interestingly, if your array represents some spatial data you can give your `dimnames` appropriate names ("lat", "lon", "latitude", "longitude", case-insensitive) and the corresponding axis will be created (if the coordinate values in the `dimnames` are within the domain of the axis type). For "time" coordinates, these are automatically detected irrespective of the name.
166
43
167
44
```{r create_dimnames}
168
-
# Note the use of named dimnames here - these will become the names of the axes
45
+
# Note the use of named dimnames: these will become the names of the axes
time = c("2025-07-01", "2025-07-02", "2025-07-03", "2025-07-04"))
171
49
172
-
(obj <- as_CF("a_better_CF_object", arr))
50
+
(obj <- as_CF("a_new_CF_object", arr))
173
51
174
52
# Axes are of a specific type and have basic attributes set
175
53
obj$axes[["lat"]]
@@ -179,34 +57,7 @@ obj$axes[["time"]]
179
57
180
58
You can further modify the resulting `CFVariable` by setting other properties, such as attributes or a coordinate reference system. Once the object is complete, you can export or save it.
181
59
182
-
## Exporting and saving data
183
-
184
-
A `CFVariable` object can be exported to a `data.table` or to a `terra::SpatRaster` (3D) or `terra::SpatRasterDataset` (4D) for further processing. Obviously, these packages need to be installed to utilise these methods.
185
-
186
-
```{r export}
187
-
# install.packages("data.table")
188
-
library(data.table)
189
-
head(dt <- ts$data.table())
190
-
191
-
#install.packages("terra")
192
-
suppressMessages(library(terra))
193
-
(r <- stats[["diurnal_range"]]$terra())
194
-
terra::plot(r)
195
-
```
196
-
197
-
A `stars` object can be created from a `CFVariable` or a `CFDataset` with multiple variables with the function `stars::st_as_stars()`.
198
-
199
-
```{r stars}
200
-
library(stars)
201
-
(st <- st_as_stars(ts))
202
-
```
203
-
204
-
A `CFVariable` object can also be written back to a netCDF file. The object will have all its relevant attributes and properties written together with the actual data: axes, bounds, attributes, CRS. The netCDF file is of version "netcdf4" and will have the axes oriented in such a way that the file has maximum portability (specifically, data will be stored in row-major order with increasing Y values).
205
-
206
-
```{r save, eval=FALSE}
207
-
# Save a CFVariable instance to a netCDF file on disk
208
-
stats[["diurnal_range"]]$save("~/path/file.nc")
209
-
```
60
+
More detailed operations and options are given on the [package web site](https://r-cf.github.io/ncdfCF/).
0 commit comments