使用 xarray 聚合点

Aggregating points using xarray

我有一组 netcdf 数据集,它们基本上看起来像一个 CSV 文件,其中包含纬度、经度和值列。这些是沿着轨道的点,我想通过计算所有落点的平均值 and/or 标准偏差,将它们聚合到从 -90 度到 90 度和 -180 度到 180 度的(比如说)1 度的规则网格在给定的单元格内。

这很容易通过循环完成

D = np.zeros((180, 360))
for ilat in np.arange(-90, 90, 1, dtype=np.int):
    for ilon in np.arange(-180, 180, 1, dtype=np.int):
        p1 = np.logical_and(ds.lat >= ilat,
                        ds.lat <= ilat + 1)
        p2 = np.logical_and(ds.lon >=ilon,
                        ds.lon <= ilon+1)
        if np.sum(p1*p2) == 0:
            D[90 + ilat, 180 +ilon] = np.nan
        else:
            D[90 + ilat, 180 + ilon] = np.mean(ds.var.values[p1*p2])
            #   D[90 + ilat, 180 + ilon] = np.std(ds.var.values[p1*p2])

除了使用 numba/cython 来加快速度之外,我想知道这是否可以更有效地直接使用 xarray 来完成?

你应该可以使用 pandas 和 xarray 来解决这个问题。

您首先需要将数据集转换为 pandas 数据框。

完成后,df 是数据框,假设经度和纬度为 lon/lat,您需要将 lon/lat 舍入到最接近的整数值,然后计算平均值每个lon/lat。然后,您需要将 lon/lat 设置为索引。然后可以用xarray的to_xarray转成数组:

import xarray as xr
import pandas as pd
import numpy as np
df = df.assign(lon = lambda x: np.round(x.lon))
df = df.assign(lat = lambda x: np.round(x.lat))
df = df.groupby(["lat", "lon"]).mean()

df = df.set_index(["lat", "lon"])
df.to_xarray()

我使用@robert-wilson 作为起点,to_xarray 确实是我解决方案的一部分。其他灵感来自 。我使用的方法如下所示。它可能比 numba-ing 我上面的解决方案慢,但简单得多。

import netCDF4
import numpy as np
import xarray as xr
import pandas as pd



fname = "super_funky_file.nc"


f = netCDF4.Dataset(fname)

lat = f.variables['lat'][:]
lon = f.variables['lon'][:]
vari = f.variables['super_duper_variable'][:]

df = pd.DataFrame({"lat":lat,
                   "lon":lon,
                   "vari":vari})

# Simple functions to calculate the grid location in rows/cols 
# using lat/lon as inputs. Global 0.5 deg grid
# Remember to cast to integer
to_col = lambda x: np.floor(
                            (x+90)/0.5).astype(
                            np.int)
to_row = lambda x: np.floor(
                            (x+180.)/0.5).astype(
                            np.int)

# Map the latitudes to columns
# Map the longitudes to rows
df['col'] = df.lat.map(to_col)
df['row'] = df.lon.map(to_row)

# Aggregate by row and col
gg = df.groupby(['col', 'row'])

# Now, create an xarray dataset with 
# the mean of vari per grid cell
ds = gg.mean().to_xarray()
dx = gg.std().to_xarray()
ds['stdi'] = dx['vari']
dx = gg.count().to_xarray()
ds['counti'] = dx['vari']```