如何使用groupby为xarray数据集添加新变量并应用?

时间:2020-07-03 22:11:29

标签: python netcdf python-xarray

在理解xarray.groupby的真正工作方式时,我面临着严重的困难。我试图在xarray DatasetGroupBy集合的每个组上应用给定的函数“ f”,以便“ f”应向原始xr.DataSet的每个应用组中添加新变量。


这里是一个简介:

我的问题通常出现在地球科学,遥感等领域。

目标是将一个给定的函数逐个像素(或逐个网格单元)应用于Array。

示例

让我们假设我要评估相对于新方向的给定区域的风场的风速分量(u,v)。因此,我希望评估'u'和'v组件的旋转版本,即:u_rotated和v_rotated。

让我们假设此新方向相对于风场中的每个像素位置逆时针旋转30°。因此,新的风分量将为(u_30_degrees和v_30_degrees)。

我的第一个尝试是将每个x和y坐标(或经度和纬度)堆叠到一个称为像素的新维度中,然后按此新维度(“像素”)进行分组,并应用一个函数来执行矢量风旋转。

这是我最初尝试的片段:

type Station struct {
    types.GormCol
    CompanyID   types.RowID            `gorm:"not null;unique" json:"company_id,omitempty"`
    CompanyName string                 `gorm:"not null;unique" json:"company_name,omitempty"`
    NodeCode    uint64                 `json:"node_code,omitempty"`
    NodeName    string                 `json:"node_name,omitempty"`
    Key         string                 `gorm:"type:text" json:"key,omitempty"`
    MachineID   string                 `json:"machine_id,omitempty"`
    Detail      string                 `json:"detail,omitempty"`
    Error       error                  `sql:"-" json:"user_error,omitempty"`
    Extra       map[string]interface{} `sql:"-" json:"extra_station,omitempty"`
}

// Validate check the type of
func (p *Station) Validate(act action.Action) error {
    fieldError := core.NewFieldError(term.Error_in_companys_form)

    switch act {
    case action.Save:
        if p.CompanyName == "" {
            fieldError.Add(term.V_is_required, "Company Name", "company_name")
        }

        if p.CompanyID == 0 {
            fieldError.Add(term.V_is_required, "Company ID", "company_id")
        }

    }

    if fieldError.HasError() {
        return fieldError
    }
    return nil
}

尽管上面的示例显然有效,但我仍然不确定其结果是否正确,或者即使groupby-apply函数实现高效(干净,非冗余,快速等)。

任何见解都将受到欢迎!

此致

1 个答案:

答案 0 :(得分:3)

您只能将整个数组乘以旋转矩阵,例如# Add .strip() to the end reply_number = urllib.parse.parse_qs(urllib.parse.urlparse(url).query)['reply'][0].strip()

因此,如果您具有以下np.dot(R, da)

Dataset

像您一样将其转换为以下>>> dims = ("x", "y") >>> sizes = (20, 30) >>> ds = xr.Dataset( data_vars=dict(u=(dims, np.ones(sizes)), v=(dims, np.ones(sizes) * 0.3)), coords={d: np.arange(s) for d, s in zip(dims, sizes)}, ) >>> ds <xarray.Dataset> Dimensions: (x: 20, y: 30) Coordinates: * x (x) int64 0 1 2 3 4 ... 16 17 18 19 * y (y) int64 0 1 2 3 4 ... 26 27 28 29 Data variables: u (x, y) float64 1.0 1.0 ... 1.0 1.0 v (x, y) float64 0.3 0.3 ... 0.3 0.3

DataArray

然后,由于>>> da = ds.stack(point=["x", "y"]).to_array(dim="wind") >>> da <xarray.DataArray (wind: 2, point: 600)> array([[1. , 1. , 1. , ..., 1. , 1. , 1. ], [0.3, 0.3, 0.3, ..., 0.3, 0.3, 0.3]]) Coordinates: * point (point) MultiIndex - x (point) int64 0 0 0 0 ... 19 19 19 19 - y (point) int64 0 1 2 3 ... 26 27 28 29 * wind (wind) <U1 'u' 'v' ,您有了旋转的值:

np.dot(R, da)

但是它是一个麻木的>>> np.dot(R, da).shape (2, 600) >>> type(np.dot(R, da)) <class 'numpy.ndarray'> 。因此,如果您想回到xarray ndarray,可以使用类似的技巧(可能存在其他解决方案):

DataArray

并像这样使用它:

def rotate(da, dim, angle):

    # Put dim first
    dims_orig = da.dims
    da = da.transpose(dim, ...)

    # Rotate
    R = rotation_matrix(angle)
    rotated = da.copy(data=np.dot(R, da), deep=True)

    # Rename values of "dim" coord according to rotation
    rotated[dim] = [f"{orig}_rotated_{angle}" for orig in da[dim].values]

    # Transpose back to orig
    return rotated.transpose(*dims_orig)

最终,您可以像这样回到原始的>>> da_rotated = rotate(da, dim="wind", angle=30) >>> da_rotated <xarray.DataArray (wind: 2, point: 600)> array([[0.7160254 , 0.7160254 , 0.7160254 , ..., 0.7160254 , 0.7160254 , 0.7160254 ], [0.75980762, 0.75980762, 0.75980762, ..., 0.75980762, 0.75980762, 0.75980762]]) Coordinates: * point (point) MultiIndex - x (point) int64 0 0 0 0 ... 19 19 19 19 - y (point) int64 0 1 2 3 ... 26 27 28 29 * wind (wind) <U12 'u_rotated_30' 'v_rotated_30' 结构:

Dataset
相关问题