首页 文章

如何更改R中的分辨率(或regrid)数据

提问于
浏览
3

我有一个由lon,lat和月平均变量(例如温度或降水)组成的数据集,涵盖1961年至1970年 . 数据集的分辨率为0.5 x 0.5度lon / lat,覆盖全球并作为a . 下载 . 我使用以下方法在R中提取数据的NC文件:

library(ncdf)
f <- open.ncdf("D:/CRU/cru_ts3.21.1961.1970.tmp.dat.nc")
A <- get.var.ncdf(nc=f,varid="tmp")
B <- get.var.ncdf(nc=f,varid="lon")
C <- get.var.ncdf(nc=f,varid="lat")
D <- cbind(expand.grid(B, C))
E <- expand.grid(A)

扩展网格(E)是由31,104,000行变量组成的数据表,扩展网格(D)是由259,200行lon / lat组成的数据表 . 如果你乘以259,200 * 10年* 12个月就得到31,104,000 . 因此,表E可以通过使用以下方式切割为月度值:

Month <- 1
Start <- (Month-1)*(259200)+1
Finish <- (Month*259200)
G <- E[Start:Finish,]
H <- expand.grid(G)
I <- cbind(D,H)

因此,我现在是第一个月(即1961年1月)的数据表,包括lon,lat和变量 . 下面给出了一个数据示例:

lon    lat tmp
49184 -68.25 -55.75 7.5
49185 -67.75 -55.75 7.6
49186 -67.25 -55.75 7.6
49899 -70.75 -55.25 6.8
49900 -70.25 -55.25 7.0
49901 -69.75 -55.25 6.9
49902 -69.25 -55.25 7.1
49903 -68.75 -55.25 6.8
49904 -68.25 -55.25 7.6
49905 -67.75 -55.25 8.2

现在我的问题 . 网格的当前分辨率为0.5 * 0.5度,我想“重新”数据,因此分辨率为0.25 * 0.25度 . 我不想做任何特别聪明的数据,所以我只想让0.25网格取其所在的0.5网格的值,即每个0.5 * 0.5网格包含4个0.25 * 0.25网格,我只想要4个0.25 * 0.25网格与0.5 * 0.5网格具有相同的值 .

我看过光栅,但似乎无法用它做任何事情 .

3 回答

  • 0

    这是一种使用 plyr::ddply() 的方法 - 可能它对于您的表大小来说有点慢,这取决于您想要重新网格化的频率 . 我将考虑使用data.table来实现它的方法,它应该更快:

    require(plyr)
    # make your data frame
    I<-data.frame(lat=seq(0.5,1000,0.5),lon=1,tmp=sample(1:100,2000,replace=T))
    
    # make an adjustment grid
    k<-expand.grid(c(0,0.25),c(0,0.25),0)
    
    # use plyr:ddply() to expand out each entry into the correponding 4 entries
    new_I<-ddply(I,.(lat,lon),function(x)as.list(x)+k)
    colnames(new_I)<-c("lat","lon","newlat","newlon","tmp")
    
    head(new_I)
    
      lat lon newlat newlon tmp
    1 0.5   1   0.50   1.00  64
    2 0.5   1   0.75   1.00  64
    3 0.5   1   0.50   1.25  64
    4 0.5   1   0.75   1.25  64
    5 1.0   1   1.00   1.00  31
    6 1.0   1   1.25   1.00  31
    

    实际上考虑一下,从时间的角度来看,这是一个更好的方法(尽管它有点像黑客,并且让你对未来可能希望做的额外数据处理的控制较少),但是2m需要6.5秒>> 8M行 .

    # make your data frame
    I<-data.frame(lat=seq(0.5,1000000,0.5),lon=1,tmp=sample(1:100,2000000,replace=T))
    
    # make an adjustment vector
    v<-rep(0.25,times=2000000)
    
    # make 3 new tables, apply the vector appropriately, and rbind
    I_latshift<-I
    I_lonshift<-I
    I_bothshift<-I
    
    I_latshift$lat<-I_latshift$lat+v
    I_lonshift$lon<-I_lonshift$lon+v
    I_bothshift$lat<-I_bothshift$lat+v
    I_bothshift$lon<-I_bothshift$lon+v
    
    I<-rbind(I,I_bothshift,I_latshift,I_lonshift)
    
    # sort it for neatness
    I<-I[with(I, order(lat, lon)), ]
    
    
    head(I)
    
             lat  lon tmp
    1       0.50 1.00   3
    6000001 0.50 1.25   3
    4000001 0.75 1.00   3
    2000001 0.75 1.25   3
    2       1.00 1.00  88
    6000002 1.00 1.25  88
    
  • 0

    R包中存在一个解决方案 raster . 它如下

    library("ncdf4")
    library("raster")
    nc <- nc_open("my_file.nc")
    lon <- ncvar_get(nc, "lon")
    lat <- ncvar_get(nc, "lat")
    time <- ncvar_get(nc, "time")
    dname <- "pre"        ## pre for the short name of precpitation 
    nlon <- dim(lon)
    nlat <- dim(lat)
    nt <- dim(time)
    lonlat <- expand.grid(lon, lat)    # make grid of given longitude and latitude 
    pr.array <- ncvar_get(nc, dname)
    dlname <- ncatt_get(nc, dname, "long_name")
    dunits <- ncatt_get(nc, dname, "units")
    fillvalue <- ncatt_get(nc, dname, "_FillValue")
    
    pr.vec.long <- as.vector(pr.array)
    pr.mat <- matrix(pr.vec.long, nrow = nlon * nlat, ncol = nt)
    pr.df <- data.frame(cbind(lonlat, pr.mat))
    
    pr_c <- pr.df[ ,-c(1:2)]
     ### Specific region have been clipped out from global datafile by 
    ## selecting lon and lat range and extract regridded data at 1lon 1lat
     ## resolution.  
    
    x0 <- seq(67.5, 98.5, by = 1) ## choose different resolution, eg. by = 0.5 
    y0 <- seq(6.5, 37.5, by = 1)
    
    
    m <- cbind(x0, y0)
    m <- as.data.frame(m)
    s <- rasterFromXYZ(m)
    pts <- expand.grid(x0, y0)
    pos <- pr.df[ ,c(1:2)]
    l_pr <- apply(pr_c, 2, function(x) cbind(pos, x))
    colnm = c("x","y","z")
    for (j in seq_along(l_pr)){
      colnames(l_pr[[j]]) <- colnm
    }
    
    pr_rstr <- lapply(l_pr, function(x) rasterFromXYZ(x))
    ## Use resample command to regrid the data, here nearest neighbor method can also be chosen by setting method = "ngb"
    pr_bn <- lapply(pr_rstr, function(x) resample(x, s, method = "bilinear"))
    pr_extr <- lapply(pr_bn, function(x) extract(x, pts))
    df_pr <- do.call("cbind", lapply(pr_extr, data.frame))
    ## write dataframe in csv format
    write.csv(df_pr, "my_data_regridded_1.csv")
    

    我希望这能达到目的 .

  • 0

    这不是R解决方案,只是要指出您可以使用CDO从linux / MAC OS环境中的命令行非常容易地重新编译netcdf文件 . 根据您的描述,听起来好像您想要使用最近邻插值,这对于0.25度的常规网格来说就是如此

    cdo remapnn,r1440x720 in.nc out.nc
    

    但是,您也可以使用一阶或二阶保守重映射 . 例如,对于第一个订单:

    cdo remapcon,r1440x720 in.nc out.nc
    

    然后,您可以按照与当前相同的方式将重新划分的字段读入R中 .

相关问题