Python 有效地获得指数的并集

Python 有效地获得指数的并集,python,performance,pandas,Python,Performance,Pandas,我有两个熊猫数据帧df1和df2,我想要它们的“合并索引” 这里我指的是当我执行例如df1.add(df2,fill\u value=0)时获得的索引。这种计算(这里,add)是在单独的脚本中执行的,我不想在这些脚本中计算“合并索引”,但我也希望在我只对“合并索引”感兴趣时避免进行这些计算 有没有更“直接”(希望更有效)的方法 我的目标实际上是将“标记”与索引元素相关联。我有几对数据帧。每对对应一个“标签”,可能有重叠的索引。不同的对对应不同的标签,它们应该没有重叠的索引 基本上,我正在寻找一个

我有两个熊猫数据帧
df1
df2
,我想要它们的“合并索引”

这里我指的是当我执行例如
df1.add(df2,fill\u value=0)时获得的索引。这种计算(这里,
add
)是在单独的脚本中执行的,我不想在这些脚本中计算“合并索引”,但我也希望在我只对“合并索引”感兴趣时避免进行这些计算

有没有更“直接”(希望更有效)的方法

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

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

dfA_1

idA_1    2    0
idA_2    1    0
idA_3    0    2
idB_1    2    2    1
idB_2    3    0    0
idB_3    3    1    3
dfA_2

idA_1    3    2    1
idA_3    2    6    2
idA_4    4    0    2
idB_1    0
idB_2    3
idB_4    2
merge_A=associate_标记((dfA_1,dfA_2),“A”)

dfB_1

idA_1    2    0
idA_2    1    0
idA_3    0    2
idB_1    2    2    1
idB_2    3    0    0
idB_3    3    1    3
dfB_2

idA_1    3    2    1
idA_3    2    6    2
idA_4    4    0    2
idB_1    0
idB_2    3
idB_4    2
merge_B=associate_标记((dfB_1,dfB_2),“B”)

total\u merge=pd.concat((merge\u A,merge\u B))

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

下面是一个不理想的实现:

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)
我计划使用这个
total\u merge
轻松地向包含混合索引元素的数据帧添加一个“tag”列。例如,我可以:

df

idA_2    5    4    1
idB_1    1    0    0
idB_4    2    1    2
idA_4    2    3    2
然后我将使用
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

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

根据您的意见,这里有一个改进的解决方案:

两部分: 结合您的数据帧,根据您的列名,您可以在确保列名对齐后,对整个数据帧列表进行pd.concat。因此,如果: dfA_1是:

       col1  col2
index            
idA_1     2     0
idA_2     1     0
idA_3     0     2
及 dfA_2是:

       col1  col2  col3
index                  
idA_1     3     2     1
idA_3     2     6     2
idA_4     4     0     2
然后

要用零填充这些NAN,请执行以下操作:

final.fillna(0, inplace=True)
第2部分,标签: 一旦您知道创建标记与定义索引映射一样简单,您就可以编写简单的函数、硬编码dict或使用lambda:

final['tag'] = final.index.map(lambda x: x[2])

final
       col1  col2  col3 tag
index                      
idA_1     2     0   0.0   A
idA_2     1     0   0.0   A
idA_3     0     2   0.0   A
idA_1     3     2   1.0   A
idA_3     2     6   2.0   A
idA_4     4     0   2.0   A

我最终发现pandas
Index
对象有一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuu
实现

希望以下版本的
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)

不知何故,我希望pandas有一种内部有效的方法来实现这一点(我想当我添加数据帧时它会这样做),这样我就不必“手动”构建重复数据消除索引。您可以使用已知标记的事实来简化解决方案的最后一步:
final[“tag”]=“A”
。此外,在我的真实案例中,无论如何都不能简单地从行名称推断标记。您知道使用
concat
是否比使用
add
更有效吗?就像我在“非理想实现”中所做的那样?是的,我只是将标记映射到第三个字符,因为这也会在示例数据中给出正确的B标记,但您可以创建一个带有离散映射或函数的dict,具体取决于实际ID的外观。您也可以将dict传递给map。我不确定concat在所有用例中是否都更有效,但它使用内置函数实现起来更简单。你没有提到速度是一个限制,但我敢打赌它至少同样好,调试起来也简单得多。如果不清楚的话,只要每个数据帧中的列名对齐,concat将处理一个数据帧列表,并按照预期的方式运行。所以不需要循环,只需要pd.concat(dfs)。您可以消除对itertools操作符和functools的需要,从而很好地清理它。