xarray指南:合并数据 - 合并
本文翻译自 xarray 官方文档 Combining data 的部分内容。
本文介绍如何使用 xarray 实现不同变量或索引的合并。
准备
本文使用《xarray指南:合并数据 - 连接》中的数据。
ds
<xarray.Dataset>
Dimensions: (x: 2, y: 3)
Coordinates:
* x (x) <U1 'a' 'b'
* y (y) int64 10 20 30
Data variables:
foo (x, y) float64 0.8927 0.7334 -0.9644 0.05414 -2.151 -1.543
Merge
想要合并多个 DataArray
和/或 Dataset
对象的变量和坐标,请使用 merge()
。
可以合并 Dataset
、DataArray
的列表,或者可以转换成 DataArray
的对象的字典。
xr.merge([
ds,
ds.rename({'foo': 'bar'}),
])
<xarray.Dataset>
Dimensions: (x: 2, y: 3)
Coordinates:
* x (x) <U1 'a' 'b'
* y (y) int64 10 20 30
Data variables:
foo (x, y) float64 0.8927 0.7334 -0.9644 0.05414 -2.151 -1.543
bar (x, y) float64 0.8927 0.7334 -0.9644 0.05414 -2.151 -1.543
xr.merge([xr.DataArray(n, name='var%d' % n) for n in range(5)])
<xarray.Dataset>
Dimensions: ()
Data variables:
var0 int64 0
var1 int64 1
var2 int64 2
var3 int64 3
var4 int64 4
如果合并另一个数据集(或包括数据数组对象的字典),默认情况下,结果数据集将在所有索引坐标的并集上对齐
other = xr.Dataset({
'bar': ('x', [1, 2, 3, 4]),
'x': list('abcd'),
})
other
<xarray.Dataset>
Dimensions: (x: 4)
Coordinates:
* x (x) <U1 'a' 'b' 'c' 'd'
Data variables:
bar (x) int64 1 2 3 4
xr.merge([ds, other])
<xarray.Dataset>
Dimensions: (x: 4, y: 3)
Coordinates:
* x (x) object 'a' 'b' 'c' 'd'
* y (y) int64 10 20 30
Data variables:
foo (x, y) float64 0.8927 0.7334 -0.9644 0.05414 ... nan nan nan nan
bar (x) int64 1 2 3 4
这将确保 merge
是非破坏性的。
如果尝试合并两个有相同名称但数据值不同的变量,则会抛出 xarray.MergeError
。
# 将会抛出异常
# xr.merge([ds, ds + 1])
这种在 DataArray
索引坐标间非破坏性的合并被用在 Dataset
的构造函数中。
xr.Dataset({
'a': arr[:-1],
'b': arr[1:],
})
<xarray.Dataset>
Dimensions: (x: 2, y: 3)
Coordinates:
* x (x) object 'a' 'b'
* y (y) int64 10 20 30
Data variables:
a (x, y) float64 0.8927 0.7334 -0.9644 nan nan nan
b (x, y) float64 nan nan nan 0.05414 -2.151 -1.543
实战
获取 850hPa 的温度场和风场
file_path=find_local_file(
"grapes_gfs_gmf/grib2/orig",
start_time="2020031800",
forecast_time="0h"
)
t850 = load_field_from_file(
file_path,
parameter="t",
level_type="isobaricInhPa",
level=850,
)
u850 = load_field_from_file(
file_path,
parameter="u",
level_type="isobaricInhPa",
level=850,
)
v850 = load_field_from_file(
file_path,
parameter="v",
level_type="isobaricInhPa",
level=850,
)
合并三个 DataArray
对象
xr.merge([t850, u850, v850])
<xarray.Dataset>
Dimensions: (latitude: 720, longitude: 1440)
Coordinates:
time datetime64[ns] 2020-03-18
step timedelta64[ns] 00:00:00
isobaricInhPa int64 850
* latitude (latitude) float64 89.88 89.62 89.38 ... -89.38 -89.62 -89.88
* longitude (longitude) float64 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8
valid_time datetime64[ns] 2020-03-18
Data variables:
t (latitude, longitude) float32 ...
u (latitude, longitude) float32 ...
v (latitude, longitude) float32 ...
Combine
实例方法 combine_first()
合并两个数据集/数据数组,并使用被调用对象中的值填充缺失数据,默认情况下调用对象中的值为非空值。
结果坐标是坐标标签的并集。
由于外部连接而导致的空单元被 NaN
填充。例如
ar0 = xr.DataArray(
[
[0, 0],
[0, 0]
],
[
('x', ['a', 'b']),
('y', [-1, 0])
]
)
ar1 = xr.DataArray(
[
[1, 1],
[1, 1]
],
[
('x', ['b', 'c']),
('y', [0, 1])
]
)
ar0.combine_first(ar1)
<xarray.DataArray (x: 3, y: 3)>
array([[ 0., 0., nan],
[ 0., 0., 1.],
[nan, 1., 1.]])
Coordinates:
* x (x) object 'a' 'b' 'c'
* y (y) int64 -1 0 1
ar1.combine_first(ar0)
<xarray.DataArray (x: 3, y: 3)>
array([[ 0., 0., nan],
[ 0., 1., 1.],
[nan, 1., 1.]])
Coordinates:
* x (x) object 'a' 'b' 'c'
* y (y) int64 -1 0 1
对于数据集,ds0.combine_first(ds1)
与 xr.merge([ds0, ds1])
效果类似。但在合并的变量中有冲突数据时,xr.merge
会抛出 MergeError
异常,而 .combine_first
默认使用被调用对象的值。
Update
与 merge
相比,update()
在不检查冲突的情况下,就地修改数据集,使用新的数据覆盖任何已存在的变量。
arr = xr.DataArray(
np.random.randn(2, 3),
[
('x', ['a', 'b']),
('y', [10, 20, 30])
]
)
ds = arr.to_dataset(name='foo')
ds
arr = xr.DataArray(
np.random.randn(2, 3),
[
('x', ['a', 'b']),
('y', [10, 20, 30])
]
)
ds = arr.to_dataset(name='foo')
ds
arr = xr.DataArray(
np.random.randn(2, 3),
[
('x', ['a', 'b']),
('y', [10, 20, 30])
]
)
ds = arr.to_dataset(name='foo')
ds
<xarray.Dataset>
Dimensions: (x: 2, y: 3)
Coordinates:
* x (x) <U1 'a' 'b'
* y (y) int64 10 20 30
Data variables:
foo (x, y) float64 0.4881 0.1385 0.8559 -0.5746 0.9708 0.3979
ds.update({
'space': ('space', [10.2, 9.4, 3.9])
})
<xarray.Dataset>
Dimensions: (space: 3, x: 2, y: 3)
Coordinates:
* x (x) <U1 'a' 'b'
* y (y) int64 10 20 30
* space (space) float64 10.2 9.4 3.9
Data variables:
foo (x, y) float64 0.4881 0.1385 0.8559 -0.5746 0.9708 0.3979
然而,不同 Dataset 变量的维度仍然需要保持一致,所以无法改变维度的大小,除非替换所有使用该维度的变量。
update
在必要时候会自动对齐。
不同于 merge
,update
保持原始数组的对齐方式,而不是合并索引。
other
<xarray.Dataset>
Dimensions: (x: 4)
Coordinates:
* x (x) <U1 'a' 'b' 'c' 'd'
Data variables:
bar (x) int64 1 2 3 4
ds.update(other)
<xarray.Dataset>
Dimensions: (space: 3, x: 2, y: 3)
Coordinates:
* x (x) object 'a' 'b'
* y (y) int64 10 20 30
* space (space) float64 10.2 9.4 3.9
Data variables:
foo (x, y) float64 0.4881 0.1385 0.8559 -0.5746 0.9708 0.3979
bar (x) int64 1 2
使用 __setitem__
语法设置变量时,使用完全相同的对齐逻辑:
ds['baz'] = xr.DataArray(
[9, 9, 9, 9, 9],
coords=[('x', list('abcde'))]
)
ds.baz
<xarray.DataArray 'baz' (x: 2)>
array([9, 9])
Coordinates:
* x (x) object 'a' 'b'
Equals and identical
可以使用 equals()
,identical()
和 broadcast_equals()
方法比较 xarray 对象。
这些方法被 concat
和 merge
的可选参数 compat
使用。
equals
检查维度名称,索引和数据值。
arr.equals(arr.copy())
True
identical
还检查属性,以及每个对象的名称
arr.identical(arr.rename("bar"))
False
broadcast_equals
进行更宽松的检查,允许变量有不同的维度,只要这些新维度的数值是常数。
left = xr.Dataset(coords={'x': 0})
right = xr.Dataset({'x': [0, 0, 0]})
left.broadcast_equals(right)
True
类似 pandas 对象,如果相同位置的缺失值被标记为 NaN
,两个 xarray 对象仍然 equal 或 identical。
相反,==
操作执行逐元素比较(类似 numpy):
arr == arr.copy()
<xarray.DataArray (x: 2, y: 3)>
array([[ True, True, True],
[ True, True, True]])
Coordinates:
* x (x) <U1 'a' 'b'
* y (y) int64 10 20 30
注意,在逐元素对比中,NaN
与 NaN
不相等。可能需要明确处理缺失值。
Merging with ’no_conflicts'
compat
参数 no_conflicts
仅在使用 merge
合并 xarray 对象时候才可用。
除上述比较方法外,它还允许将两个都具有 NaN
值位置的 xarray 对象合并。
只要任何非缺失值一致或不相交,就可以将其与重叠坐标的数据合并使用:
ds1 = xr.Dataset(
{
'a': ('x', [10, 20, 30, np.nan])
},
{
'x': [1, 2, 3, 4]
}
)
ds1
<xarray.Dataset>
Dimensions: (x: 4)
Coordinates:
* x (x) int64 1 2 3 4
Data variables:
a (x) float64 10.0 20.0 30.0 nan
ds2 = xr.Dataset(
{
'a': ('x', [np.nan, 30, 40, 50])
},
{
'x': [2, 3, 4, 5]
}
)
ds2
<xarray.Dataset>
Dimensions: (x: 4)
Coordinates:
* x (x) int64 2 3 4 5
Data variables:
a (x) float64 nan 30.0 40.0 50.0
xr.merge([ds1, ds2])
<xarray.Dataset>
Dimensions: (x: 5)
Coordinates:
* x (x) int64 1 2 3 4 5
Data variables:
a (x) float64 10.0 20.0 30.0 40.0 50.0
xr.merge([ds1, ds2], compat='no_conflicts')
<xarray.Dataset>
Dimensions: (x: 5)
Coordinates:
* x (x) int64 1 2 3 4 5
Data variables:
a (x) float64 10.0 20.0 30.0 40.0 50.0
请注意,由于缺失值的基本表示为浮点数(NaN
),因此以这种方式合并时并不总是保留可变数据类型。