当使用 Python 2.7 的 xarray 包时,是否可以像 pandas 那样对多个参数进行分组?本质上,像这样的操作:
data.groupby(['time.year','time.month']).mean()
Run Code Online (Sandbox Code Playgroud)
如果您想获取数据集每年和每月的平均值。
假设我有一个datasetof 类型xarray.Dataset。我有一个名为 的维度name(由DataArray中的所有 s共享Dataset,但我认为这对于这个问题并不重要),并且我想选择一个具有特定名称的条目。我会按如下方式执行此操作。
dataset.sel(name="lucifer")
Run Code Online (Sandbox Code Playgroud)
但假设我现在想要选择一个包含名称“lucifer”和“judas”的子数据集。我想做一些类似的事情:
dataset.sel(name=["lucifer", "judas"])
Run Code Online (Sandbox Code Playgroud)
因为这是我能想象到的最接近 Pandas 的语法。但这给了我一个错误。
InvalidIndexError: Reindexing only valid with uniquely valued Index objects
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,我从 Xarray 得到的每个错误似乎都是这个确切的错误,我真的很高兴看到 Xarray 给出更多信息性错误。)所以我的问题是,如何从命名维度中选择多个命名值?假设命名值没有特定的顺序,因此我不能使用切片。
我需要为a添加维度DataArray,在新维度上填充值.这是原始数组.
a_size = 10
a_coords = np.linspace(0, 1, a_size)
b_size = 5
b_coords = np.linspace(0, 1, b_size)
# original 1-dimensional array
x = xr.DataArray(
np.random.random(a_size),
coords=[('a', a coords)])
Run Code Online (Sandbox Code Playgroud)
我想我可以创建一个带有新维度的空DataArray并复制现有数据.
y = xr.DataArray(
np.empty((b_size, a_size),
coords=([('b', b_coords), ('a', a_coords)])
y[:] = x
Run Code Online (Sandbox Code Playgroud)
一个更好的想法可能是使用concat.我花了一段时间才弄清楚如何为concat维度指定dims和coords,并且这些选项都不是很好.有什么我想念的东西可以使这个版本更干净吗?
# specify the dimension name, then set the coordinates
y = xr.concat([x for _ in b_coords], 'b')
y['b'] = b_coords
# specify the coordinates, then rename the dimension
y = xr.concat([x for _ in …Run Code Online (Sandbox Code Playgroud) 是否有一种简单的方法可以将 xarray 数据集展平为单个 1D numpy 数组?
例如,展平以下测试数据集:
xr.Dataset({
'a' : xr.DataArray(
data=[10,11,12,13,14],
coords={'x':[0,1,2,3,4]},
dims={'x':5}
),
'b' : xr.DataArray(data=1,coords={'y':0}),
'c' : xr.DataArray(data=2,coords={'y':0}),
'd' : xr.DataArray(data=3,coords={'y':0})
})
Run Code Online (Sandbox Code Playgroud)
到
[10,11,12,13,14,1,2,3]
Run Code Online (Sandbox Code Playgroud)
?
我计划在我正在编写的一些数字密集型科学代码中广泛使用 xarray。到目前为止,它使代码非常优雅,但我认为我将不得不放弃它,因为性能成本太高了。
这是一个示例,它创建两个数组并使用 xarray(具有多个索引方案)和 numpy 将它们的一部分相乘。我使用了 num_comp=2 和 num_x=10000:
Line # Hits Time Per Hit % Time Line Contents
4 @profile
5 def xr_timing(num_comp, num_x):
6 1 4112 4112.0 10.1 da1 = xr.DataArray(np.random.random([num_comp, num_x]).astype(np.float32), dims=['component', 'x'], coords={'component': ['a', 'b'], 'x': np.linspace(0, 1, num_x)})
7 1 438 438.0 1.1 da2 = da1.copy()
8 1 1398 1398.0 3.4 da2[:] = np.random.random([num_comp, num_x]).astype(np.float32)
9 1 7148 7148.0 17.6 da3 = da1.isel(component=0).drop('component') * da2.isel(component=0).drop('component')
10 1 6298 6298.0 15.5 da4 = da1[dict(component=0)].drop('component') * da2[dict(component=0)].drop('component') …Run Code Online (Sandbox Code Playgroud) 我对 xarray 相当陌生,我目前正在尝试利用它来对某些 NetCDF 进行子集化。我在共享服务器上运行它,想知道如何最好地限制 xarray 使用的处理能力,以便它与其他人很好地合作。我已经阅读了 dask 和 xarray 文档,但我似乎不清楚如何设置 cpus/线程的上限。以下是空间子集的示例:
import glob
import os
import xarray as xr
from multiprocessing.pool import ThreadPool
import dask
wd = os.getcwd()
test_data = os.path.join(wd, 'test_data')
lat_bnds = (43, 50)
lon_bnds = (-67, -80)
output = 'test_data_subset'
def subset_nc(ncfile, lat_bnds, lon_bnds, output):
if not glob.os.path.exists(output):
glob.os.makedirs(output)
outfile = os.path.join(output, os.path.basename(ncfile).replace('.nc', '_subset.nc'))
with dask.config.set(scheduler='threads', pool=ThreadPool(5)):
ds = xr.open_dataset(ncfile, decode_times=False)
ds_sub = ds.where(
(ds.lon >= min(lon_bnds)) & (ds.lon <= max(lon_bnds)) & (ds.lat >= min(lat_bnds)) & …Run Code Online (Sandbox Code Playgroud) 我想将我的 xarray 对象重新采样到较低的空间分辨率(LESS PIXELS)。
import pandas as pd
import numpy as np
import xarray as xr
time = pd.date_range(np.datetime64('1998-01-02T00:00:00.000000000'), np.datetime64('2005-12-28T00:00:00.000000000'), freq='8D')
x = np.arange(1200)
y = np.arange(1200)
latitude = np.linspace(40,50,1200)
longitude = np.linspace(0,15.5572382,1200)
latitude, longitude = np.meshgrid(latitude, longitude)
BHR_SW = np.ones((365, 1200, 1200))
output_da = xr.DataArray(BHR_SW, coords=[time, y, x])
latitude_da = xr.DataArray(latitude, coords=[y, x])
longitude_da = xr.DataArray(longitude, coords=[y, x])
output_da = output_da.rename({'dim_0':'time','dim_1':'y','dim_2':'x'})
latitude_da = latitude_da.rename({'dim_0':'y','dim_1':'x'})
longitude_da = longitude_da.rename({'dim_0':'y','dim_1':'x'})
output_ds = output_da.to_dataset(name='BHR_SW')
output_ds = output_ds.assign({'latitude':latitude_da, 'longitude':longitude_da})
print(output_ds)
<xarray.Dataset> …Run Code Online (Sandbox Code Playgroud) 我有一组数据框,代表我已放入字典中的需求场景。我需要遍历字典中的每个数据框以重新索引和重新采样等并返回到字典。当我遍历数据帧列表时,下面的代码工作得很好,但我需要维护每个场景的身份,因此是字典。
这是与数据框列表一起使用的代码:
demand_dfs_list = [low_demand_df, med_low_demand_df, bc_demand_df, med_high_demand_df, high_demand_df]
dates = pd.date_range(start='2020-10-01', end='2070-09-30', freq='D')
demand_dfs_datetime = []
for df in demand_dfs_list:
df.index = pd.to_datetime(df.index, format='%Y')
df = df.tshift(-92, 'D')
df = df.resample('D').ffill()
df = df.reindex(dates)
demand_dfs_datetime.append(df)
Run Code Online (Sandbox Code Playgroud)
这是我以字典形式尝试过的:
demand_scenarios = {'low': low_demand_df, 'medium_low': med_low_demand_df, 'medium': bc_demand_df, 'medium_high': med_high_demand_df, 'high': high_demand_df}
dates = pd.date_range(start='2020-10-01', end='2070-09-30', freq='D')
demand_dict = {}
for df in demand_scenarios:
[df].index = pd.to_datetime([df].index, format='%Y')
[df] = [df].tshift(-92, 'D')
[df] = [df].resample('D').ffill()
[df] = [df].reindex(dates)
demand_dict[df] = df
Run Code Online (Sandbox Code Playgroud)
跟进问题 …
为了清楚起见,我已经基本上重新表述了我之前的问题。根据 Ryan 在单独频道上的建议, numpy.digitize 看起来是实现我目标的正确工具。
我有一个形状为 x、y 和时间的 xarray.DataArray。我试图弄清楚应该为apply_ufunc函数的“input_core_dims”和“output_core_dims”参数提供哪些值,以便应用于numpy.digitize时间序列中的每个图像。
直观地说,我希望输出维度为 ['time', 'x', 'y']。我认为输入核心维度应该是x,y因为我想numpy.digitize沿着时间维度广播函数。然而这行不通。通过将 numpy.digitize 应用于我的时间序列中的第一个 numpy 数组,我得到了正确的结果:
[84]
blues
<xarray.DataArray 'reflectance' (time: 44, y: 1082, x: 1084)>
dask.array<shape=(44, 1082, 1084), dtype=uint16, chunksize=(44, 1082, 1084)>
Coordinates:
band int64 1
* y (y) float64 9.705e+05 9.705e+05 9.705e+05 ... 9.673e+05 9.672e+05
* x (x) float64 4.889e+05 4.889e+05 4.889e+05 ... 4.922e+05 4.922e+05
* time (time) datetime64[ns] 2018-10-12 2018-10-16 ... 2019-05-26
Attributes:
transform: (3.0, 0.0, …Run Code Online (Sandbox Code Playgroud) 我处于一种情况,我想加载对象,将它们转换为一个xarray.Dataset并将其写入 s3 上的 zarr 存储。但是,为了更快地加载对象,我使用 Dask 集群跨不同年份并行执行,因此,也希望并行写入 s3。这里的一般结构是:
def my_task(year, store, synchronizer):
# load objects for that year
...
dataset = ...
# I want to append this data to a zarr store on S3
dataset.to_zarr(store, append_dim="time", synchronizer=synchronizer)
futures = []
for y in years:
futures.append(client.submit(my_task, y, same_store, synchronizer))
client.gather(futures)
Run Code Online (Sandbox Code Playgroud)
但是,这样做会失败:当多个工作人员同时写入时,存储会进入不一致的状态。我试过使用,zarr.sync.ProcessSynchronizer但问题仍然存在,类似于这种情况:How can one write lock a zarr store during append?
任何帮助或指导将不胜感激。谢谢!
python-xarray ×10
python ×6
dask ×1
dictionary ×1
for-loop ×1
netcdf ×1
netcdf4 ×1
pandas ×1
performance ×1
resampling ×1
time-series ×1
xarray ×1
zarr ×1