2017-09-03 52 views
2

我有两个dataframes这样的:高效串联忽略后缀

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 

所以,我想连接独立后缀suf1的dataframes df2的索引中的suf2。由于c1df1中的条目对于列A为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 

问题是是否存在在那里更有效和更通用的解决方案的工作,并且还分别非工作的情况下,。

回答

3

使用join通过MultiIndex产生分裂的df2indexreindexMultiindexdf1的:

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 
+1

非常漂亮(upvoted)!似乎有效地解决了我的两个问题。 – Cleb

+0

@cᴏʟᴅsᴘᴇᴇᴅ - 是的,这是另一种解决方案。祝你好运! – jezrael

1

我不认为你需要转换到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 
+0

谢谢,似乎也很好,(upvoted);仍然需要弄清楚为什么“分裂”的鼻涕会出现在任何地方。 ;) – Cleb