首页 > 解决方案 > 关于索引的 bin 成员资格添加两个系列的 Pandonic 方法

问题描述

设置

>>> import pandas as pd
>>> import numpy as np
>>> s1 = pd.Series([100, 1000, 10000], index=[0, 2, 5])
s1
0      100
2     1000
5    10000
dtype: int64
>>> s2 = pd.Series(np.arange(7)*10)
>>> s2
0     0
1    10
2    20
3    30
4    40
5    50
6    60
dtype: int32

假设:

澄清s2:不能假设索引有任何特定的顺序!

期望的结果

我想将 的值添加s1到如下的值中s2(请参阅注释以获取解释):

>>> result
0      100 # 100 + 0, because index 0 is in [0, 2)
1      110 # 100 + 10, because index 1 is in [0, 2)
2     1020 # 1000 + 20, because index 2 is in [2, 5)
3     1030 # 1000 + 20, because index 3 is in [2, 5)
4     1040 # 1000 + 40, because index 4 is in [2, 5)
5    10050 # 10000 + 50, because index 5 is in [5, inf)
6    10060 # 10000 + 50, because index 6 is in [5, inf)
dtype: int64

试图

我创建了 bins 的版本s1和索引的位置。s2

>>> edges = [*s1.index, np.inf]
>>> s1_binned = pd.Series(s1.values, index=pd.cut(s1.index, bins=edges, right=False))
>>> s2_binned = pd.Series(s2.values, index=pd.cut(s2.index, bins=edges, right=False))
s1_binned
[0.0, 2.0)      100
[2.0, 5.0)     1000
[5.0, inf)    10000
dtype: int64
>>> s2_binned
[0.0, 2.0)     0
[0.0, 2.0)    10
[2.0, 5.0)    20
[2.0, 5.0)    30
[2.0, 5.0)    40
[5.0, inf)    50
[5.0, inf)    60
dtype: int32

然后我使用索引s1进行索引s2以获取要添加的值。

>>> to_add = s1_binned[s2_binned.index]
>>> to_add
[0.0, 2.0)      100
[0.0, 2.0)      100
[2.0, 5.0)     1000
[2.0, 5.0)     1000
[2.0, 5.0)     1000
[5.0, inf)    10000
[5.0, inf)    10000
dtype: int64

最后我可以添加to_addto的值s2

>>> s2 + to_add.values
0      100
1      110
2     1020
3     1030
4     1040
5    10050
6    10060
dtype: int64

我觉得有更好的解决方案,但我没有太多将值“映射”到垃圾箱的经验。

标签: pythonpandas

解决方案


您的感觉是正确的-有一种更令人沮丧的方式:

s2+s1.reindex_like(s2).fillna(method='ffill')

让我们分解一下:

  • s1.reindex_like(s2)返回一个索引为 like 的系列s2NaN其中添加了新索引(即空行):

  • fillna(method='ffill')用前一个非空值填充每个空行

已编辑: 在评论中,OP 解释说s2' 索引不假定已排序。
例如:

import pandas as pd
import numpy as np
s1 = pd.Series([100, 1000, 10000], index=[0, 2, 5])
s2 = pd.Series(np.arange(7)*10)
s2 = s2[[2,3,5,1,0,4,6]]

所以s2就是

2    20
3    30
5    50
1    10
0     0
4    40
6    60
dtype: int64

显然,我的方法仍然有效:

s2+s1.reindex_like(s2, method='ffill')

退货

2     1020
3     1030
5    10050
1      110
0      100
4     1040
6    10060
dtype: int64

如果我理解正确,那是所需的输出。


推荐阅读