Windows下tidync运行异常:无法将过滤后的nc对象转为数据框
问题:Windows下tidync处理netCDF文件崩溃,求替代方案或配置方法
我有一系列netCDF文件,希望过滤维度后转换为数据框。该操作在Mac上可正常运行,但在Windows电脑上执行hyper_tibble()或hyper_array()函数时,无报错信息,函数始终无法完成,最终导致R崩溃。预期输出仅约3000行,因此并非文件大小问题。
数据结构如下(使用tidync查看):
library(tidync) nc <- tidync(url) print(nc)
输出:
Data Source (1): cmems_mod_nws_phy-uv_my_7km-2D_PT1H-i ... Grids (4) <dimension family> : <associated variables> [1] D1,D0,D2 : vo, uo **ACTIVE GRID** ( 28796229000 values per variable) [2] D0 : latitude [3] D1 : longitude [4] D2 : time Dimensions 3 (all active): dim name length min max start count dmin dmax unlim coord_dim <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <dbl> <dbl> <lgl> <lgl> 1 D0 latitude 375 40.1 65.0 1 375 40.1 65.0 FALSE TRUE 2 D1 longitude 297 -19.9 13.0 1 297 -19.9 13.0 FALSE TRUE 3 D2 time 258552 725850000 1656633600 1 258552 725850000 1656633600 FALSE TRUE
我通过以下代码子集化数据:
## SUBSET .NC DATA y <- -2.3 x <- 56.5 nc_sub <- nc %>% hyper_filter(latitude = index == which.min(abs(latitude - y)), # closest lat/lon in nc to my x and y longitude = index == which.min(abs(longitude - x)), time = dplyr::between(time, "2021-11-22 09:59:00 UTC", "2022-03-15 13:59:00 UTC")) print(nc_sub)
输出:
Grids (4) <dimension family> : <associated variables> [1] D1,D0,D2 : vo, uo **ACTIVE GRID** ( 28796229000 values per variable) [2] D0 : latitude [3] D1 : longitude [4] D2 : time Dimensions 3 (all active): dim name length min max start count dmin dmax unlim coord_dim <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <dbl> <dbl> <lgl> <lgl> 1 D0 latitude 375 40.1 65.0 248 1 56.5 56.5 FALSE TRUE 2 D1 longitude 297 -19.9 13.0 159 1 -2.33 -2.33 FALSE TRUE 3 D2 time 258552 725850000 1656633600 253258 2716 1637575200 1647349200 FALSE TRUE
最终执行nc_tib <- nc_sub %>% hyper_tibble()、nc_sub %>% hyper_array()、nc_sub %>% hyper_slice(select_var = "vo")均会导致R冻结。请问是否有其他实现方法(可脱离tidync包),或Windows上的包配置方案?
解决方案
一、Windows下tidync的配置调整
- 检查NetCDF/GDAL依赖:tidync依赖底层的NetCDF和GDAL库,Windows上可通过安装
sf包自动配置兼容的依赖库,或手动安装OSGeo4W提供的NetCDF组件,确保库版本更新且兼容。 - 调整内存限制:在Windows启动R时增加内存分配,比如右键R快捷方式,修改目标为
"C:\Program Files\R\R-x.x.x\bin\Rgui.exe" --max-mem-size=8G(根据自身内存调整数值)。 - 更换tidync版本:尝试安装旧版本(如
devtools::install_version("tidync", version = "1.0.2"))或开发版(devtools::install_github("hypertidy/tidync")),版本兼容性可能解决崩溃问题。
二、脱离tidync的替代方法
方法1:使用ncdf4手动读取子集
ncdf4是直接操作netCDF文件的基础包,手动指定索引读取数据,避免tidync的潜在兼容性问题:
library(ncdf4) library(dplyr) library(lubridate) # 打开netCDF文件 nc <- nc_open("你的文件名.nc") # 获取维度数据 lat <- ncvar_get(nc, "latitude") lon <- ncvar_get(nc, "longitude") time_raw <- ncvar_get(nc, "time") # 转换时间戳为UTC datetime(需匹配原数据的时间单位,这里假设是秒级) time_dt <- as_datetime(time_raw, tz = "UTC") # 定位目标经纬度的索引 target_lat_idx <- which.min(abs(lat - 56.5)) target_lon_idx <- which.min(abs(lon - (-2.3))) # 筛选时间范围对应的索引 time_idx <- which(between(time_dt, ymd_hms("2021-11-22 09:59:00", tz = "UTC"), ymd_hms("2022-03-15 13:59:00", tz = "UTC"))) # 读取变量数据,指定起始位置和读取数量 vo <- ncvar_get(nc, "vo", start = c(target_lon_idx, target_lat_idx, min(time_idx)), count = c(1, 1, length(time_idx))) uo <- ncvar_get(nc, "uo", start = c(target_lon_idx, target_lat_idx, min(time_idx)), count = c(1, 1, length(time_idx))) # 关闭文件连接 nc_close(nc) # 整理为数据框 result_df <- tibble( time = time_dt[time_idx], latitude = lat[target_lat_idx], longitude = lon[target_lon_idx], vo = as.vector(vo), uo = as.vector(uo) )
方法2:使用terra包(简洁高效)
terra处理栅格/时间序列netCDF文件更便捷,支持直接提取点数据:
library(terra) library(dplyr) library(lubridate) # 读取netCDF文件为栅格对象 r <- rast("你的文件名.nc") # 创建目标点的矢量对象 target_point <- vect(data.frame(x = -2.3, y = 56.5), crs = "EPSG:4326") # 提取点的时间序列数据(simple为精确匹配点,bilinear为插值) point_data <- extract(r, target_point, method = "simple") # 筛选时间范围 time_r <- time(r) time_filter <- between(time_r, ymd_hms("2021-11-22 09:59:00", tz = "UTC"), ymd_hms("2022-03-15 13:59:00", tz = "UTC")) # 整理为数据框 result_df <- point_data %>% select(vo, uo) %>% mutate( time = time_r[time_filter], latitude = 56.5, longitude = -2.3 ) %>% relocate(time, latitude, longitude)
方法3:使用stars包(tidy风格兼容)
stars支持tidyverse语法,直接筛选维度:
library(stars) library(dplyr) library(lubridate) # 读取netCDF文件为stars对象 nc_stars <- read_stars("你的文件名.nc") # 筛选目标经纬度和时间范围,转换为数据框 result_df <- nc_stars %>% filter( latitude == which.min(abs(latitude - 56.5)), longitude == which.min(abs(longitude - (-2.3))), time >= ymd_hms("2021-11-22 09:59:00", tz = "UTC"), time <= ymd_hms("2022-03-15 13:59:00", tz = "UTC") ) %>% as_tibble()
内容的提问来源于stack exchange,提问作者billyleaf
相关产品推荐
相关产品推荐

