在理解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函数实现高效(干净,非冗余,快速等)。
任何见解都将受到欢迎!
此致
答案 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