使用 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']```
我有一组 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
确实是我解决方案的一部分。其他灵感来自
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']```