高效连接忽略索引中的后缀

Efficient concatenation ignoring suffixes in index

我确实有两个这样的数据框:

import pandas as pd

df1 = pd.DataFrame({"c1": range(5), "c2": range(1, 6)}, index=list("ABCDE"))
df2 = pd.DataFrame({"c3": range(15, 21), "c4": range(11, 17)}, index=["A_suf1", "B_suf2", "A_suf2", "C_suf2", "B_suf1", "D_suf1"])   

   c1  c2    
A   0   1
B   1   2
C   2   3
D   3   4
E   4   5

        c3  c4
A_suf1  15  11
B_suf2  16  12
A_suf2  17  13
C_suf2  18  14
B_suf1  19  15
D_suf1  20  16

我想变成

       c3  c4  c1
A_suf1  15  11   0
B_suf2  16  12   1
A_suf2  17  13   0
C_suf2  18  14   2
B_suf1  19  15   1
D_suf1  20  16   3

所以,我想在 df2 的索引中连接独立于后缀 suf1suf2 的数据帧。由于列 Adf1 中的 c1 中的条目为 0,因此它应该出现在条目 A_suf1A_suf2 的串联数据框中。

我目前的实现方式如下:

# store original name of index
old_index = df2.index
# temporary column which creates values which are in the the index of df1
df2['helper'] = df2.reset_index()["index"].apply(lambda x: x.split("_")[0]).tolist()
# prepare concat
df2 = df2.set_index("helper")
# concat
df_final = pd.concat([df2, df1.loc[:, "c1"]], join="inner", axis=1)
# reset index to original values
df_final.index = old_index

这给了我想要的输出。

然而,它需要一个相当慢的 apply,并且如果 df2 中有一个不在 df1 中的索引条目,它也会失败。例如,上面的代码将因 df2 等于

而失败
df2 = pd.DataFrame({"c3": range(15, 22), "c4": range(11, 18)}, index=["A_suf1", "B_suf2", "A_suf2", "C_suf2", "B_suf1", "D_suf1", "F_suf1"])

        c3  c4
A_suf1  15  11
B_suf2  16  12
A_suf2  17  13
C_suf2  18  14
B_suf1  19  15
D_suf1  20  16
F_suf1  21  17

因此,问题是是否有分别针对工作和非工作情况的更有效和通用的解决方案。

df1Multiindex 使用 join by MultiIndex created splitted index of df2 with reindex

df2.index = df2.index.str.split('_', expand=True)
print(df2)
        c3  c4
A suf1  15  11
B suf2  16  12
A suf2  17  13
C suf2  18  14
B suf1  19  15
D suf1  20  16

print (df1['c1'].reindex(df2.index,level=0))
A  suf1    0
B  suf2    1
A  suf2    0
C  suf2    2
B  suf1    1
D  suf1    3
Name: c1, dtype: int32

df = df2.join(df1['c1'].reindex(df2.index,level=0))
#convert MultiIndex to index
df.index = df.index.map('_'.join)
print (df)
        c3  c4  c1
A_suf1  15  11   0
B_suf2  16  12   1
A_suf2  17  13   0
C_suf2  18  14   2
B_suf1  19  15   1
D_suf1  20  16   3

另一个df2得到:

print (df)
        c3  c4   c1
A_suf1  15  11  0.0
B_suf2  16  12  1.0
A_suf2  17  13  0.0
C_suf2  18  14  2.0
B_suf1  19  15  1.0
D_suf1  20  16  3.0
F_suf1  21  17  NaN

我认为您不需要转换为 MultiIndex。您可以只提取索引并使用 df.locpd.concat 加入。

idx = [x[0] for x in df2.index]
out = pd.concat([df2, df1.loc[idx, ['c1']].set_index(df2.index)], 1)
print(out)
        c3  c4  c1
A_suf1  15  11   0
B_suf2  16  12   1
A_suf2  17  13   0
C_suf2  18  14   2
B_suf1  19  15   1
D_suf1  20  16   3

对于你的第二个数据框,我得到

        c3  c4   c1
A_suf1  15  11  0.0
B_suf2  16  12  1.0
A_suf2  17  13  0.0
C_suf2  18  14  2.0
B_suf1  19  15  1.0
D_suf1  20  16  3.0
F_suf1  21  17  NaN

性能

# converting to MultiIndex
100 loops, best of 3: 3.57 ms per loop

# using `df.loc` and `df.set_index`
1000 loops, best of 3: 1.53 ms per loop