有效地连接多个 pandas 系列

Concatenate multiple pandas series efficiently

我知道我可以使用 combine_first 合并两个系列:

series1 = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'])
series2 = pd.Series([1,2,3,4,5],index=['f','g','h','i','j'])
series3 = pd.Series([1,2,3,4,5],index=['k','l','m','n','o'])

Combine1 = series1.combine_first(series2)
print(Combine1

输出:

a    1.0
b    2.0
c    3.0
d    4.0
e    5.0
f    1.0
g    2.0
h    3.0
i    4.0
j    5.0
dtype: float64

如果我需要合并 3 个或更多系列怎么办?

我理解使用以下代码:print(series1 + series2 + series3)产量:

a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
f   NaN
...
dtype: float64

我可以在不多次使用 combine_first 的情况下有效地合并多个系列吗?

谢谢

同意@codespeed 在他的回答中指出的内容。

我认为这将取决于用户需求。如果确认系列索引没有重叠,concat 将是更好的选择。 (作为原始问题发布,没有索引重叠,然后 concat 将是一个更好的选择)

如果存在索引重叠,您可能需要考虑如何处理重叠,要覆盖哪个值。 (如codespeed提供的例子,如果索引匹配不同的值,需要注意combine_first)

即(注意series3和series1一样,series2和series4一样)

import pandas as pd
import numpy as np


series1 = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'])
series2 = pd.Series([2,3,4,4,5],index=['a','b','c','i','j'])
series3 = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'])
series4 = pd.Series([2,3,4,4,5],index=['a','b','c','i','j'])


print(series1.combine_first(series2))



a    1.0
b    2.0
c    3.0
d    4.0
e    5.0
i    4.0
j    5.0
dtype: float64



print(series4.combine_first(series3))



a    2.0
b    3.0
c    4.0
d    4.0
e    5.0
i    4.0
j    5.0
dtype: float64

如果您希望一个系列的值优先于另一个系列,则可以使用 combine_first。它通常用于填充第一个系列中的缺失值。我不确定您的示例中的预期输出是什么,但看起来您可以使用 concat

pd.concat([series1, series2, series3])

你得到

a    1
b    2
c    3
d    4
e    5
f    1
g    2
h    3
i    4
j    5
k    1
l    2
m    3
n    4
o    5

将序列与非重叠索引合并

要垂直合并系列,请使用 pd.concat

# Setup
series_list = [
    pd.Series(range(1, 6), index=list('abcde')),
    pd.Series(range(1, 6), index=list('fghij')),
    pd.Series(range(1, 6), index=list('klmno'))
]

pd.concat(series_list)

a    1
b    2
c    3
d    4
e    5
f    1
g    2
h    3
i    4
j    5
k    1
l    2
m    3
n    4
o    5
dtype: int64

结合重叠索引

series_list = [
    pd.Series(range(1, 6), index=list('abcde')),
    pd.Series(range(1, 6), index=list('abcde')),
    pd.Series(range(1, 6), index=list('kbmdf'))
]

如果系列有重叠索引,您可以组合(添加)键,

pd.concat(series_list, axis=1, sort=False).sum(axis=1)

a     2.0
b     6.0
c     6.0
d    12.0
e    10.0
k     1.0
m     3.0
f     5.0
dtype: float64

或者,如果您只想获取 first/last 值(当存在重复项时),只需将重复值放在索引中即可。

res = pd.concat(series_list, axis=0)
# keep first value
res[~res.index.duplicated(keep='first')]
# keep last value
res[~res.index.duplicated(keep='last')]

假设您正在使用 combine_first 的行为来按 combine_first 的目的对系列值进行优先排序,您可以使用 lambda 表达式简洁地对其进行多次调用。

from functools import reduce
l_series = [series1, series2, series3]
reduce(lambda s1, s2: s1.combine_first(s2), l_series)

当然,如果索引像您当前的示例一样是唯一的,您可以简单地使用 pd.concat 代替。

演示

series1 = pd.Series(list(range(5)),index=['a','b','c','d','e'])
series2 = pd.Series(list(range(5, 10)),index=['a','g','h','i','j'])
series3 = pd.Series(list(range(10, 15)),index=['k','b','m','c','o'])

from functools import reduce
l_series = [series1, series2, series3]
print(reduce(lambda s1, s2: s1.combine_first(s2), l_series))

# a     0.0
# b     1.0
# c     2.0
# d     3.0
# e     4.0
# g     6.0
# h     7.0
# i     8.0
# j     9.0
# k    10.0
# m    12.0
# o    14.0
# dtype: float64