我正在与xarray一起根据另一个数据集的值的条件创建一个新的数据集。
输入数据集对象ds_season
按季节排列,并具有以下三个维度。
<xarray.Dataset>
Dimensions: (latitude: 106, longitude: 193, season: 4)
Coordinates:
* latitude (latitude) float32 -39.2 -39.149525 ... -33.9
* longitude (longitude) float32 140.8 140.84792 ... 150.0
* season (season) object 'DJF' 'JJA' 'MAM' 'SON'
Data variables:
FFDI 95TH PERCENTILE (season, latitude, longitude) float64 dask.array<shape=(4, 106, 193), chunksize=(4, 106, 193)>
我需要创建一个新的数据集,该数据集具有纬度,经度和时间三个维度。纬度和经度应与输入数据集的坐标相同,时间坐标应为10年以上的天数。
例如,结果数据集如下:
<xarray.Dataset>
Dimensions: (latitude: 106, longitude: 193, time: 3653)
Coordinates:
* latitude (latitude) float32 -39.2 -39.149525 ... -33.950478 -33.9
* longitude (longitude) float32 140.8 140.84792 140.89584 ... 149.95209 150.0
* time (time) datetime64[ns] 1972-01-01T00:00:00 1972-01-02T00:00:00 1972-01-03T00:00:00 ... 1981-12-30T00:00:00 1981-12-31T00:00:00
Data variables:
FFDI 95TH PERCENTILE (time, latitude, longitude) float64 dask.array<shape=(3653, 106, 193), chunksize=(3653, 106, 193)>
一天的变量应与该天的季节的变量相同。这意味着1972-01-01、1972-02-02和1972-02-28的值应与DJF的季节;和1972-04-01、1972-05-02和1972-05-31应该具有与MAM季节相同的值。
我正在考虑数据集的where()函数,但是不知道从哪里开始。 http://xarray.pydata.org/en/stable/generated/xarray.Dataset.where.html?highlight=where#xarray.Dataset.where
答案 0 :(得分:0)
首先,请注意。创建一个新的DataArray,连续3个月每天复制相同的空间数据,可能会占用大量的磁盘空间,而没有任何意义。我宁愿每当您需要特定日期的数据时查询季节DataArray。 但是,如果您确实需要执行此操作并回答您的问题,我认为最简单的方法是:
在下面的示例中,我创建了一个季节DataArray进行测试。如果我确切地理解了您的问题,那么您应该能够使用原始数组,而无需在第二部分中进行太多更改(使用foo创建)。
让我们开始吧。首先是进口:
import xarray as xr
import numpy as np
import pandas as pd
创建所需大小的空容器。
data_s = np.zeros((4, 10, 10))
用虚拟值填充它。
data_s[0] = 0.5
data_s[1] = 0.9
data_s[2] = 0.8
data_s[3] = 0.45
创建虚拟坐标。
x = y = np.arange(10)
创建季节索引。
seasons = ["spring", "summer", "autumn", "winter"]
最后,创建DataArray。
bar = xr.DataArray(data_s, coords=[seasons, x, y], dims=['season', 'x', 'y'])
bar是要从中提取季节性值的DataArray。 现在,对单个日期重复相同的操作。
创建一个为期2000天的容器数组,我们将使用每个季节的数据进行填充。
data = np.ones((2000, 10, 10))
x = y = np.arange(10)
dates = pd.date_range('2000-01-01', periods=2000)
在这里,我假设是从每月的第一天开始的北方季节(从here借来。 当然,您可以轻松编写更好的函数,例如使用一年中的某天获取季节。
season = np.array((dates.month %12 + 3)//3)
创建字典,将上面的数字转换为先前在bar中分配的季节的字符串
seas_to_num = {1:"spring", 2:"summer", 3:"autumn", 4:"winter"}
我们每天用bar [season]上的值填充数组。
for date, seas in enumerate(season):
data[date] = bar.sel(season=seas_to_num[seas])
最后,我们创建DataArray。
foo = xr.DataArray(data, coords=[dates, x, y], dims=['time', 'x', 'y'])
现在选择4月5日,我们将获得spring的值。
In [1]: foo.sel(time=pd.to_datetime("5/4/2001"))
Out[1]:
array([[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9],
[0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9]])
Coordinates:
time datetime64[ns] 2001-05-03
* x (x) int32 0 1 2 3 4 5 6 7 8 9
* y (y) int32 0 1 2 3 4 5 6 7 8 9
答案 1 :(得分:0)
我同意安德里亚(Andrea)的观点,即创建具有3653个唯一天数(仅复制4个不同季节值)的数据集通常效率不高。如果您提供有关实现此目标的更多信息,也许我们可以建议其他解决方案。
假设您确实要执行此操作,最快的方法可能是使用xarray的groupby broadcasting arithmetic。接下来,我将假设ds
是您原始帖子(尺寸为(latitude: 106, longitude: 193, time: 3653)
的第二个数据集的名称)。然后,您可以像这样
zeros = xr.zeros_like(ds)
filled_in = zeros.groupby('time.season') + ds_season
此建议的灵感来自我们通常根据季节气候学计算异常的方式:
# original dataset with dimensions 'time'
ds = xr.open_dataset(...)
# climatology has dimension 'season'
ds_climatology = ds.groubpy('time.season').mean(dim='time')
# anomaly has dimension 'time'
ds_anomaly = ds.groubpy('time.season') - ds_climatology