在 3D 数组 NetCDF 文件中查找每年的最大值(使用 Pandas 或 xarray 的方法?)

问题描述 投票:0回答:3

我正在尝试从几个 NetCDF 文件中制作一些地图等数据。每一项都包含 5 年的数据。数据位于形状为

(14608, 145, 192)
(时间、纬度、经度)的 3D 数组中。

我想要每个坐标每年的最大值,所以基本上当一切都说完并完成后,我将得到一个形状为

(5,145,192)
的输出数组(每个纬度和经度值一个值)。

有人建议我尝试使用 pandas,特别是 DataFrame 和 DatetimeIndex,但我找不到一种方法来将它用于比 2D 数组更大的东西。还建议使用 Xarray,但我以前没有使用过 xarray,不知道从哪里开始。

编辑 1:示例数据

这是我一直尝试用 pandas 做的简化版本,然后我意识到 DataFrame 不适用于 3D 数组。

import numpy as np
import pandas as pd

fake = np.random.randint(2, 30, size = (14608,145,192))
index = pd.date_range(start = '1985-1-1 01:30:00', end = '1989-12-31 22:30:00' , freq='3H')

df = pd.DataFrame(data = fake, index = index)

编辑 2:固定列出的数组形状

为了澄清,我实际上想要一个形状为

(5, 145, 192)
的数组作为输出。我写错了,因为最初我将 3D 数组分成 5 个单独的数组,找到最大值,然后将它们再次堆叠到一个以
(5, 145, 192)
形状结尾的数组中。

我希望能够跳过我之前所做的手动分解数组的繁琐工作并简化代码。

python arrays pandas max netcdf
3个回答
4
投票

以下是使用 Xarray 解决此问题的方法:

import xarray as xr

# open one of your files
ds = xr.open_dataset('path/to/your/ncfile.nc')

# find maximum for a specific year (1990 in this example)
ds_ymax = ds.sel(time=slice('1990-01-01', '1990-12-31')).max('time')

# plot a single variable ('temperature' in this example)
ds_ymax['temperature'].plot()

虽然这涵盖了您想要做的事情的基础知识,但我认为我应该提到一些其他常见的工作流程:

  1. 一次打开多个文件。 Xarray 提供了

    open_mfdataset
    功能,允许一次快速串联多个文件:

    ds = xr.open_mfdataset('path/to/your/ncfiles/*nc')  # note the use of the wildcard
    
  2. 使用resample计算年度最大值。在上面的示例中,我手动选择了一年的数据,但可以使用 resample 或 groupby 以编程方式执行此操作

    # using resample ('AS' == annual starting Jan-1)
    ds_ymax = ds.resample(time='AS').max('time')
    
    # using groupby
    ds_ymax = ds.groupby('time.year').max('time')
    

最后,您提到不知道从哪里开始使用 xarray。查看文档:http://xarray.pydata.org/en/latest/index.html


1
投票

如果您想要年度最大值(即每年每个网格点一个值),那么您可以使用

cdo
:

从命令行执行此操作
cdo yearmax in.nc out.nc 

您可以通过使用 cdo 包在 python 中使用这些函数,安装时:

pip install cdo

所以Python代码是

from cdo import Cdo
cdo=Cdo()
cdo.yearmax(input="in.nc",output="out.nc")

更多详细信息请参见:https://code.mpimet.mpg.de/projects/cdo/embedded/index.html


0
投票

您可以在这里使用

Panel

df = pd.Panel(fake).to_frame()
df.columns=index
df
Out[1065]: 
             1985-01-01 01:30:00  1985-01-01 04:30:00  1985-01-01 07:30:00
major minor                                                               
0     0                       28                    7                   22
      1                        9                   10                   11
      2                        8                   15                    7
      3                       19                   18                    2
      4                       14                   16                   24
      5                        6                   26                   13
      6                       28                   16                   11

#....
© www.soinside.com 2019 - 2024. All rights reserved.