如何从多个每日文件中获取运行平均值或移动平均值

时间:2019-03-27 05:29:43

标签: python netcdf python-xarray

我每天有11年(2007年至2017年)温度记录。共有11*365 = 4015个NetCDF文件。每个文件均包含纬度(100,),经度(360,)以及温度变量(360, 100)。我想找到每个网格点的15天运行(移动)平均值,而忽略NaN值(如果存在)。这意味着需要使用15个文件来查找均值。我具有以下功能,可以从文件夹中读取所有日常文件。例如需要找到files_list[0:15]files_list[1:16]files_list[2:17]....files_list[4000:]的平均值。每个文件意味着需要另存为新的NetCDF文件。我有一个创建NetCDF文件的想法。但是找不到移动平均线。

这是我的代码:

def files_list (working_dir, extension):
    '''
    input = working directory and extension of file(eg. *.nc)
    outout = returns the list of files in the folder
    '''
    file_full_path = os.path.join(working_dir)
    os.chdir(working_dir)
    files = glob.glob(os.path.join(file_full_path,extension)) 
    files = natsort.natsorted(files)
    files_list= []       #Empty lsit of files
    j = 0 
    for j in range(0,len(files)):
        files_list.append(os.path.basename(files[j])) #appending each files in a directory to file list 
    return files_list

3 个答案:

答案 0 :(得分:2)

这不是python中的解决方案,但是如果您的文件名为file_20061105.nc等,则可以从命令行将其与cdo(气候数据运算符)合并,然后使用runmean函数

cdo mergetime file_*.nc merged_file.nc
cdo runmean,15 merged_file.nc runmean.nc

在某些系统上,可以打开的文件数量受到限制,在这种情况下,您可能需要每年一次合并文件

for year in {2007..2017} ; do 
  cdo mergetime file_${year}????.nc merged_${year}.nc
done
cdo mergetime merged_????.nc merged_file.nc
cdo runmean,15 merged_file.nc runmean.nc

这是从命令行快速完成此操作的另一种方法。

如果您想在python程序中执行此任务,则可以首先以这种方式将文件分类为一个文件(或循环使用python中的文件并将它们读入100x360x4000的单个numpy数组中),然后在python中执行运行平均值,这里已经有关于此任务的stackoverflow问题:

Moving average or running mean

答案 1 :(得分:1)

关于我上面的评论:

  

“每个文件中有多少个项目?...如果每个文件包含数千个网格点,我会   首先将不同的网格点排序为单独的文件。每   文件将对所有日期保持相同的网格点,并按日期排序。这个   加载单个网格点的整个文件很简单   并计算出其运行平均值。”

现在您有了一个用于单个网格点的文件,我将把数据加载到列表中并运行此简单的移动平均值计算。 (由于您已访问整个数据集,因此可以使用此代码。对于在运行中计算平均值而没有结果历史记录的情况,可以使用此处指定的算法:Wikipedia - Moving Average

#Generate a list of 10 items
my_gridpoints_data=[x for x in range(1, 11)]
print(my_gridpoints_data)

#The average calculation window is set to 3, so the average is for 3 items at a time
avg_window_width: int = 3
avg: float = 0.0
sum: float = 0.0

# Calculate the average of the first 3 items (avg_window_width is 3)
for pos in range(0, avg_window_width):
    sum = sum + my_gridpoints_data[pos]
avg = sum / avg_window_width
print(avg)

# Then move the window of the average by subtracting the leftmost item 
# and adding a new item from the right
# Do this until the calculation window reaches the list's last item

for pos in range(avg_window_width, my_gridpoints_data.__len__()):
    sum = sum + my_gridpoints_data[pos] - my_gridpoints_data[pos - avg_window_width]
    avg = sum/avg_window_width
    print(avg)

结果输出为:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
2.0
3.0
4.0
5.0
6.0
7.0
8.0

答案 2 :(得分:0)

回答得有点晚,但对于将来阅读的人,xarray还提供了一种非常简单的Pythonic解决方案,与@Adrian Tomkins回答非常相似,该解决方案可以首先合并每年的文件,然后将它们合并在一起。一个文件,因为系统中可以打开的文件数有限。

for yr in range(2011,2018):
    file_name = str(yr) + 'merge.nc'
    xr.open_mfdataset(str(yr)*, combine='nested', concat_dim='time').to_netcdf(file_name)

xr.open_mfdataset(*merge.nc, combine='nested', concat_dim='time').to_netcdf(merge_all.nc)
ds = xr.open_dataset(merge_all.nc, chunks={'lat'=10, 'lon'=10}) # option to chunk if file size is too large, can also be used earlier with open_mfdataset
ds_rolling_mean = ds.rolling(time=15, center=True).mean()

编辑:xarray相对于其他经典工具的一大优势在于,借助dask,可以轻松进行内存不足的计算并在多个内核上扩展计算。例如,如果您必须在合并之前对文件进行一些预处理,则xr.open_mfdataset将用户定义的预处理函数用作preprocess参数,并设置'parallel = True'将对输入进行预处理合并前并行处理文件。