从2000年到2014年,我每年有15个netCDF文件(.nc)。在一个nc文件中,我有8760层的一个变量的每小时数据。 3个维度是: 时间(8760号), 纬度(尺寸90)和 经度(大小180)(2°分辨率)。
我想计算2000年至2014年4月至9月的上午8点至晚上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
答案 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数组,请添加该维度。而且,如果您想查找更多信息,则可以使用特定时间值作为平均值,这在气象科学中通常称为复合技术。
我希望这可以解决您的问题。