【问题标题】:Merge several Series with different indexes, summing over duplicated indexes合并多个具有不同索引的系列,对重复的索引求和
【发布时间】:2019-04-16 18:53:24
【问题描述】:

假设我有三个系列

s1 = pd.Series(data=np.arange(5))
s2 = pd.Series(data=np.arange(5),index=np.arange(2,7))
s3 = pd.Series(data=np.arange(5),index=np.arange(5,10))

将它们合并成一个系列的最有效方法是将重复索引中的data 值求和,并将值保留在非重复索引中。换句话说,对于s1s2s3,我们期望输出:

0    0
1    1
2    2
3    4
4    6
5    3
6    5
7    2
8    3
9    4

实际上,我们可以有大量的数据条目,因此循环效率不高。

【问题讨论】:

  • 该系列的所有索引都会按升序排列吗?它们都是正数吗?
  • 不一定,也可能是标签类型

标签: python pandas numpy dataframe


【解决方案1】:

让我们在这里使用concatsum

pd.concat([s1, s2, s3]).sum(level=0)

0    0
1    1
2    2
3    4
4    6
5    3
6    5
7    2
8    3
9    4
dtype: int64

串联是一个 O(n) 操作(线性复杂度),建议 99% 的时间。


如果你喜欢方法链,这个适合你。

s1.append(s2).append(s3).sum(level=0)

0    0
1    1
2    2
3    4
4    6
5    3
6    5
7    2
8    3
9    4
dtype: int64

不推荐用于超过 3 个系列。一次添加两个结果是复杂度的二次方。

【讨论】:

  • 很好 - 我猜 concat 正在处理引擎盖下的外部连接。
  • @ojlm 这在技术上不是 Join 操作,因为您只是垂直连接。 join 参数在水平合并它们时会有所不同。以下是关于该主题的详尽讨论:stackoverflow.com/questions/53645882/pandas-merging-101
【解决方案2】:

这是一个使用 NumPy 工具的工具 -

def sum_series(L): # L is list of series
    aL = [list(l.index) for l in L]
    intL,unqL = pd.factorize(np.concatenate(aL))
    sums = np.bincount(intL,np.concatenate(L))
    return pd.Series(sums, index=unqL)

示例运行 -

In [158]: L = [s1,s2,s3] # list of series

In [159]: sum_series(L)
Out[159]: 
0    0.0
1    1.0
2    2.0
3    4.0
4    6.0
5    3.0
6    5.0
7    2.0
8    3.0
9    4.0
dtype: float64

使用通用标签 -

In [170]: L
Out[170]: 
[Label0    0
 Label1    1
 Label2    2
 Label3    3
 Label4    4
 dtype: int64, Label2    0
 Label3    1
 Label4    2
 Label5    3
 Label6    4
 dtype: int64, Label5    0
 Label6    1
 Label7    2
 Label8    3
 Label9    4
 dtype: int64]

In [171]: sum_series(L)
Out[171]: 
Label0    0.0
Label1    1.0
Label2    2.0
Label3    4.0
Label4    6.0
Label5    3.0
Label6    5.0
Label7    2.0
Label8    3.0
Label9    4.0
dtype: float64

版本 #2

在数组数据上使用连接并使用智能输出 dtype,可能会通过类似这样的方式获得更理想的输出 -

def sum_series_v2(L): # L is list of series
    aL = [list(l.index) for l in L]
    v = [l.values for l in L]
    intL,unqL = pd.factorize(np.concatenate(aL))
    sums = np.bincount(intL,np.concatenate(v))
    dtype = np.result_type(*[l.dtype for l in L])
    return pd.Series(sums.astype(dtype), index=unqL)

示例运行 -

In [225]: sum_series_v2(L)
Out[225]: 
Label0    0
Label1    1
Label2    2
Label3    4
Label4    6
Label5    3
Label6    5
Label7    2
Label8    3
Label9    4
dtype: int64

【讨论】:

  • 不错的替代方法
猜你喜欢
  • 2018-09-17
  • 1970-01-01
  • 1970-01-01
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多