R的不同层和几个netcdf文件的平均值

时间:2018-10-02 13:03:08

标签: r average netcdf

从2000年到2014年,我每年有15个netCDF文件(.nc)。在一个nc文件中,我有8760层的一个变量的每小时数据。 3个维度是: 时间(8760号), 纬度(尺寸90)和 经度(大小180)(2°分辨率)。

我想计算2000年至2014年4月至9月的上午8点至晚上7点之间的变量平均值。

对于一个.nc文件,这对应于之间的平均值

  • 图层时间从2169(即2000年4月1日上午8点)到2180(即2000年1月4日下午7点)(到i = 2169到i + 11),
  • 然后从2193(即2000年4月2日上午8点)到2204(即2000年4月2日晚上7点)(i + 22,i + 33)
  • 等...
  • ...以及从6537(即2000年9月30日上午8点)到6548(即2000年9月30日晚上7点)
  • 然后是所有nc的平均值。文件。

结果应显示在一个3维的.nc文件中: -时间(平均值只有一个值), -纬度(尺寸90)和 -经度(180号尺寸)(2°分辨率)

然后,我可以绘制2000-2014年(4月至9月,上午8点至晚上7点)平均变量的地图。 我能够读取每个nc文件,为每个nc文件的每个小时做一个映射,但是我知道如何计算所需的均值。如果有人可以帮助我,那就太好了。

我的变量名:dname <-“ sfvmro3”

这是我的拳头代码:

ncin <- nc_open("sfvmro3_hourly_2000.nc")
print(ncin)

lon <- ncvar_get(ncin, "lon")
lon[lon > 180] <- lon[lon > 180] - 360
nlon <- dim(lon)
head(lon)

lat <- ncvar_get(ncin, "lat", verbose = F)
nlat <- dim(lat)
head(lat)

print(c(nlon, nlat))

t <- ncvar_get(ncin, "time")
tunits <- ncatt_get(ncin, "time", "units")
nt <- dim(t)

dname <- "sfvmro3"
var.array <- ncvar_get(ncin, dname)*10^9  # from mol.mol-1 to ppb
dlname <- ncatt_get(ncin, dname, "long_name")
dunits <- ncatt_get(ncin, dname, "units")
fillvalue <- ncatt_get(ncin, dname, "_FillValue")
var.array[var.array == fillvalue$value] <- NA
dim(var.array)

tustr <- strsplit(tunits$value, " ")
tdstr <- strsplit(unlist(tustr)[3], "-")
tyear = as.integer(unlist(tdstr)[1])
tmonth = as.integer(unlist(tdstr)[2])
tday = as.integer(unlist(tdstr)[3])
chron = chron(t, origin = c(tmonth, tday, tyear))

以下是一份年度文件的详细信息。nc:

 4 variables (excluding dimension variables):
    double time_bnds[bnds,time]   
    double lat_bnds[bnds,lat]   
    double lon_bnds[bnds,lon]   
    float sfvmro3[lon,lat,time]   
        standard_name: mole_fraction_of_ozone_in_air
        long_name: Ozone Volume Mixing Ratio in the Lowest Model Layer
        units: mole mole-1
        original_name: O_x
        original_units: 1
        history: 2016-04-22T05:20:31Z altered by CMOR: Converted units from '1' to 'mole mole-1'.
        cell_methods: time: point (interval: 30 minutes)
        cell_measures: area: areacella
        missing_value: 1.00000002004088e+20
        _FillValue: 1.00000002004088e+20
        associated_files: ...

 4 dimensions:
    time  Size:8760   *** is unlimited ***
        bounds: time_bnds
        units: days since 1850-01-01
        calendar: noleap
        axis: T
        long_name: time
        standard_name: time
    lat  Size:90
        bounds: lat_bnds
        units: degrees_north
        axis: Y
        long_name: latitude
        standard_name: latitude
    lon  Size:180
        bounds: lon_bnds
        units: degrees_east
        axis: X
        long_name: longitude
        standard_name: longitude
    bnds  Size:2

26 global attributes:
    institution: aaaa
    institute_id: aaaa
    experiment_id: aaaa
    source: aaaa
    model_id: aaaa
    forcing: HG, SA, S
    parent_experiment_id: N/A
    parent_experiment_rip: N/A
    branch_time: 0
    contact: aaa
    history: aaa
    initialization_method: 1
    physics_version: 1
    tracking_id: aaa
    product: output
    experiment: aaa
    frequency: hr
    creation_date: 2016-04-22T05:20:31Z
    Conventions: aaa
    project_id: aaa
    table_id:aaa
    title: aaaa
    parent_experiment: N/A
    modeling_realm: aaa
    realization: 1
    cmor_version: 2.7.1

1 个答案:

答案 0 :(得分:0)

我知道您的问题有两种不同的解决方案。一种是基于对每个.nc文件取平均值,然后对其进行加权平均,另一种则是获得一个非常大的数组并使用该数组取平均值。

  • 第一个可能的解决方案

您阅读的每个.nc都将为您提供array和array1,array2等。同样,对于每个数组,您将有一个与数组的一个维度相关联的时间序列。这意味着time_serie1具有array1的POSIXct格式的所有不同时间。因此,首先您必须构建该向量。您可以获得一个要用于平均的时间的向量索引。为此,我将使用lubridate软件包,但这不是必需的。

index1 <- month(time_serie1) < 10 & month(time_serie1) > 3 # this make an index from april to septembre
index1 <- index1 & hour(time_serie1) <= 19 & hour(time_serie1) >= 8 # then you add the hour restriction
mean1 <- apply(array1[,,index1],1:2,mean)

此代码将为您提供一个二维数组,其中包含第一年的平均值,您可以将数组和time_series放入列表中并进行循环。然后,您将每年获得该年平均值的二维数组,并且可以对该数组取平均值。我说的“加权”平均数部分是因为,如果您这样做,并且在平均数中包括2月,则您的均值将花费不同的天数(例如,您不必这样做),但是如果使用2月,则表示必须权衡用于每个平均值的数据量。

  • 第二种可能的解决方案

此解决方案与另一解决方案几乎相同,但我更喜欢它。您可以按顺序将所有数组合并到一个大数组中,这样时间索引的顺序将递增,我将此数组称为BigArray。然后合并与每个数组关联的时间序列,我将其称为BigTime。然后寻找您想要平均的索引,并完成。最大的优点是您不必遍历列表中的数据,也不必担心2月的大小更改。

Index <- month(BigTime) < 10 & month(BigTime) > 3 # this make an index from april to septembre
Index <- Index & hour(BigTime) <= 19 & hour(BigTime) >= 8 # then you add the hour restriction
Mean <- apply(BigArray[,,Index],1:2,mean) 

然后就完成了您的价值观平均值。

在两种可能的情况下,都将构建一个2d数组,如果您想要一个只有一个值追逐的具有一个维度(时间)的3d数组,请添加该维度。而且,如果您想查找更多信息,则可以使用特定时间值作为平均值,这在气象科学中通常称为复合技术。

我希望这可以解决您的问题。