高效获取pandas索引的并集

bli*_*bli 4 python performance pandas

我有两个熊猫数据框df1df2我想要它们的“合并索引”。

我的意思是当我这样做时获得的索引df1.add(df2, fill_value=0).index(基本上,行名称的联合)。这种计算(此处为add)在单独的脚本中执行,我不想在这些脚本中计算“合并索引”,但是当我只对“合并索引”。

有没有更“直接”(希望有效)的方法来做到这一点?

我的目标实际上是将“标签”与索引元素相关联。我有几对数据框。每一对对应一个“标签”并且可能有重叠的索引。不同的对对应不同的标签,并且它们应该没有重叠的索引。

基本上,我正在寻找一个associate_tag函数的有效实现,该函数的工作方式如下:

dfA_1

idA_1    2    0
idA_2    1    0
idA_3    0    2
Run Code Online (Sandbox Code Playgroud)

dfA_2

idA_1    3    2    1
idA_3    2    6    2
idA_4    4    0    2
Run Code Online (Sandbox Code Playgroud)

merge_A = associate_tag((dfA_1, dfA_2), "A")

idA_1    A
idA_2    A
idA_3    A
idA_4    A
Run Code Online (Sandbox Code Playgroud)

dfB_1

idB_1    2    2    1
idB_2    3    0    0
idB_3    3    1    3
Run Code Online (Sandbox Code Playgroud)

dfB_2

idB_1    0
idB_2    3
idB_4    2
Run Code Online (Sandbox Code Playgroud)

merge_B = associate_tag((dfB_1, dfB_2), "B")

idB_1    B
idB_2    B
idB_3    B
idB_4    B
Run Code Online (Sandbox Code Playgroud)

total_merge = pd.concat((merge_A, merge_B))

idA_1    A
idA_2    A
idA_3    A
idA_4    A
idB_1    B
idB_2    B
idB_3    B
idB_4    B
Run Code Online (Sandbox Code Playgroud)

我知道要与给定数据帧对的索引元素关联的标签,associate_tag理想情况下,该函数会完全忽略数据帧中的数字。

这是一个非理想的实现:

from functools import reduce
from itertools import repeat

def add_dataframes(df1, df2):
    return df1.add(df2, fill_value=0)

def sum_dataframes(dfs):
    return reduce(add_dataframes, dfs)

def associate_tag(dfs, tag):
    return pd.concat((sum_dataframes(dfs).index, repeat(tag)), axis=1)

def associate_tag(dfs, tag):   
    s = sum_dataframes(dfs)
    return pd.DataFrame(list(zip(s.index, repeat(tag)))).set_index(0)
Run Code Online (Sandbox Code Playgroud)

我计划使用它total_merge来轻松地将“标签”列添加到包含索引元素混合的数据帧。例如,我可以有:

df

idA_2    5    4    1
idB_1    1    0    0
idB_4    2    1    2
idA_4    2    3    2
Run Code Online (Sandbox Code Playgroud)

然后我会用pd.concat((df, total_merge), join="inner", axis=1)标签添加一个额外的列:

idA_2    5    4    1    A
idB_1    1    0    0    B
idB_4    2    1    2    B
idA_4    2    3    2    A
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做这种操作?

bli*_*bli 5

我终于发现 pandasIndex对象有一个__or__实现。

希望以下版本associate_tag避免多余的操作:

from operator import or_ as union
from itertools import repeat
from functools import reduce

def associate_tag(dfs, tag):   
    idx = reduce(union, (df.index for df in dfs))
    return pd.DataFrame(list(zip(idx, repeat(tag)))).set_index(0)
Run Code Online (Sandbox Code Playgroud)