pandas - 即使索引值恰好一致,也可以跨 pandas MultiIndex 级别广播
问题描述
这个让我难住了。我有两个pd.Series
s
,t
如下:
Common Level s
Foo a 1
b 2
Name: s, dtype: int64
Common Level t
Foo A 10
B 20
Name: t, dtype: int64
pandas
让我添加这些和跨通用级别的广播'Common'
输入:
s + t
输出:
Common Level s Level t
Foo a A 11
B 21
b A 12
B 22
dtype: int64
现在考虑另一个pd.Series
u
索引标签恰好与s
Common Level u
Foo a 100
b 200
Name: u, dtype: int64
换句话说,我们有(s.index.values == u.index.values).all()
回报True
。正因为如此,pandas
不再广播
输入:
s + u
输出:
Common Level s
Foo a 101
b 202
dtype: int64
即使s.index.names
和u.index.names
不同意。
最后,如果更改了顺序但没有更改标签,例如 for v
:
Common Level v
Foo b 1000
a 2000
Name: v, dtype: int64
因此,s.index.values
如果v.index.values
不完全同意,就会发生广播。
输入:
s + v
输出:
Common Level s Level v
Foo a b 1001
a 2001
b b 1002
a 2002
dtype: int64
我的问题:我怎样才能添加s
这样u
的pandas
仍然广播?(对于我的特定应用程序,我实际上对 elementwise-and 感兴趣,而s & u
不是 sum s + u
。)
代码
s = pd.Series([1, 2],
index=pd.MultiIndex.from_tuples(
[('Foo', 'a'), ('Foo', 'b')],
names=['Common', 'Level s']), name='s')
t = pd.Series([10, 20],
index=pd.MultiIndex.from_tuples(
[('Foo', 'A'), ('Foo', 'B')],
names=['Common', 'Level t']), name='t')
u = pd.Series([100, 200],
index=pd.MultiIndex.from_tuples(
[('Foo', 'a'), ('Foo', 'b')],
names=['Common', 'Level u']), name='u')
v = pd.Series([1000, 2000],
index=pd.MultiIndex.from_tuples(
[('Foo', 'b'), ('Foo', 'a')],
names=['Common', 'Level v']), name='v')
解决方案
为广播标准化 Series 和 DataFrames 的索引所调用的方法是align
. 这个方法在内部被调用来获取新的索引,我们可以看到:
left, right = s.align(t, join='outer', level=None, copy=False)
# left
Common Level s Level t
Foo a A 1
B 1
b A 2
B 2
Name: s, dtype: int64
# right
Common Level s Level t
Foo a A 10
B 20
b A 10
B 20
Name: t, dtype: int64
请注意,当索引相等时,此调用将产生“非广播”值,因为外部连接产生单个级别:
left, right = s.align(u, join='outer', level=None, copy=False)
# left
Common Level s
Foo a 1
b 2
Name: s, dtype: int64
# right
Common Level u
Foo a 100
b 200
Name: u, dtype: int64
如果我们想强制生成级别,我们可以_align_series
在索引不相等时使用 for 的分支:
join_index, lidx, ridx = self.index.join( other.index, how=join, level=level, return_indexers=True ) left = self._reindex_indexer(join_index, lidx, copy) right = other._reindex_indexer(join_index, ridx, copy)
我们可以使用Index.join
and_reindex_indexer
创建对齐的系列:
join_index, lidx, ridx = s.index.join(
u.index, how='outer', level=None, return_indexers=True
)
left = s._reindex_indexer(join_index, lidx, copy=False)
right = u._reindex_indexer(join_index, ridx, copy=False)
*注意:我们使用的是私有方法,因为公共 API 中没有等效的重新索引器。
现在我们已经对齐了 Series,我们可以这样做:
left + right
要获得结果:
Common Level s Level u
Foo a a 101
b 201
b a 102
b 202
dtype: int64
如果我们想避免使用私有方法,我们还iloc
可以使用索引位置选择值,然后set_axis
用带有适当标签的连接索引覆盖:
join_index, lidx, ridx = s.index.join(
u.index, how='outer', level=None, return_indexers=True
)
left = s.iloc[lidx].set_axis(join_index)
right = u.iloc[ridx].set_axis(join_index)
left + right
Common Level s Level u
Foo a a 101
b 201
b a 102
b 202
dtype: int64
推荐阅读
- javascript - 为什么我来自 BehivourSubject 的消息会重复每条新收到的消息?
- visual-studio-code - 为 vs 代码启用和禁用 Python 扩展没有效果
- javascript - 未捕获(承诺)错误:上传后控制台中的文件堆栈选择器初始化错误
- windows-10 - L如何将新的图标覆盖链接到我的应用程序?
- laravel - Laravel 验证 ID 是否具有关系实例
- java - Java 10 copyOf 工厂方法是否适合构造函数中的防御性副本
- android - 夜间模式不会更新启动画面的颜色
- swift - 在 macOS 10.15.7 (19H1030) 上渲染 CIImage 会导致空白图像
- spring-data-jpa - 通过spring批处理从数据库中读取并从数据库中删除
- java - JPA:致命错误编译:java.lang.NoClassDefFoundError:javax/persistence/spi/PersistenceUnitInfo:javax.persistence.spi.PersistenceUnitInfo