I'm trying to wrestle some netcdf files containing daily climate data into .csv files. This is usually a routine task but I got this set of files that seems problematic. The error occurred (see below) where I needed to convert the matrices to dataframe and I couldn't figure out what the issue is. The error doesn't occur when I'm not looping through the files. Any tips would be appreciated.
Here's my code. Sample data can be found here sample data.
library(stringr)
library(ncdf4)
fin <- list.files("D:/path/prec", pattern = ".nc$", full.names=TRUE)
fin2 <- gsub("D:/path/prec/", "", fin)
var_name = str_replace(fin2, ".nc", "") ## generates data file names
for(i in seq_along(fin)){
prec <- nc_open(fin[i])
var = ncvar_get(prec, var_name[i], collapse_degen = F)
dim_lon <- ncvar_get(prec, "longitude")
dim_lat <- ncvar_get(prec, "latitude")
dim_time <- ncvar_get(prec, "time")
coords = as.matrix(expand.grid(dim_lon, dim_lat, dim_time))
r = data.frame(cbind(coords, var)) **this is where the problem is!**
names(r) = c("Lon", "Lat", "Day", "Prec")
i = var_name[i] ##assign name to match input name
write.csv(prec, file.path("D:/path/prec", paste0(i, ".csv")), row.names = FALSE)
}
Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) : cannot coerce class ‘"ncdf4"’ to a data.frame.
Expected outcome:
Lon Lat Day Prec
-133.25 60.25 127 10.74618626
-133 60.25 127 11.28547573
-132.75 60.25 127 11.23372364
-132.5 60.25 127 11.06846809
-132.25 60.25 127 10.87025547
-132 60.25 127 9.392285347
Found a different approach using tidync
, which solved the problem. The new approach is more efficient than my original code.
library(stringr)
library(tidync)
fin <- list.files("D:/path/prec", pattern = ".nc$", full.names=TRUE)
fin2 <- gsub("D:/path/prec/", "", fin)
var_name = str_replace(fin2, ".nc", "") ## generates data file names
for(i in seq_along(fin)) {
prec <- tidync(fin[i])
prec = prec %>%
hyper_tibble()
names(prec) = c("Prec", "Lon", "Lat", "Time")
i = var_name[i] ##assign name to match input name
write.csv(prec, file.path("D:/path/prec", paste0(i, ".csv")), row.names = FALSE)
}
Here's the output
# Prec Lon Lat Time
# 0.0000122 -141 69.6 284038200
# 0.00000904 -141 69.6 284038200
# 0.00000805 -141 69.6 284038200
# 0.00000732 -141 69.6 284038200
# 0.00000244 -140 69.6 284038200
# 0.00000316 -140 69.6 284038200
Note that the time is supposed to be in days but this is how it's presented in the source file and has nothing to do with the extraction method. Any tips for conversion would be appreciate.