如何使用DataArray where()函数根据条件从另一个DataArray赋值

2024-05-18 21:41:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在与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年以上的天数。在

例如,生成的数据集如下所示:

^{pr2}$

一天的变量应该与该天所在季节的变量相同。这意味着,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


Tags: 数据时间where条件datasetseasonxarraylatitude
2条回答

首先,一张便条。创建一个新的DataArray,每天复制相同的空间数据,持续3个月,可能会占用大量磁盘空间而没有太大意义。我宁愿在您每次需要特定日期的数据时查询季节数据数组。 但是,如果您真的需要执行此操作,并回答您的问题,我认为最直接的方法是:

  1. 首先,创建一个新容器np.ndarray公司是个好主意。在
  2. 然后,建立日期索引
  3. 查询你原来的季节数据数组
  4. 最后,使用维度时间创建一个新的DataArray。在

在下面的示例中,我创建了一个用于测试的季节数据数组。如果我完全理解您的问题,那么在第二部分(通过foo的创建),您应该能够使用原始数组而不需要做太多更改。在

我们开始吧。首先是进口:

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

创建所需大小的空容器。在

^{pr2}$

用虚拟值填充它。在

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日,我们得到春天的值。在

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

我同意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

这个建议的灵感来自于我们通常从季节气候学计算异常的方法:

^{pr2}$

相关问题 更多 >

    热门问题