我有两个要合并的表df_a
和df_b
,但是两个表都缺少一些值。合并进行得很好,但是我正在尝试加快合并后填充NaN
值的过程。
df_a = pd.DataFrame(data={
'id': [1, 2, 3, 1, 6, 5, 3],
'name': [np.nan, 'two', 'three', 'one', np.nan, np.nan, np.nan],
'length': ['l1', 'l2', 'l3', 'l1', 'l6', np.nan, np.nan],
'Q1': [11, 22, 33, 11, 66, 55, 33],
'Q2': [111, 222, 333, 111, 666, 555, 333]})
df_b = pd.DataFrame(data={
'id': [5, 2, 4, 1, 3, 1, 7, 3],
'name': ['five', 'two', 'four', 'one_extra', 'three', 'one', 'seven', 'three'],
'length': ['l5', 'l2', 'l4', 'l1', 'l3', 'l1', 'l7', 'l3_extra'],
'Q1': [2055, 2022, 2044, 2011, 2033, 2011, 2077, 2033],
'Q2': [2055, 2022, 2044, 2011, 2033, 2011, 2077, 2033]})
df_m = df_a.merge(df_b, on=['id', 'name', 'length'], how='outer',
suffixes=['_a', '_b'])
Output:
id name length Q1 Q2
0 1 NaN l1 11 111
1 2 two l2 22 222
2 3 three l3 33 333
3 1 one l1 11 111
4 6 NaN l6 66 666
5 5 NaN NaN 55 555
6 3 NaN NaN 33 333
id name length Q1 Q2
0 5 five l5 2055 2055
1 2 two l2 2022 2022
2 4 four l4 2044 2044
3 1 one_extra l1 2011 2011
4 3 three l3 2033 2033
5 1 one l1 2011 2011
6 7 seven l7 2077 2077
7 3 three l3_extra 2033 2033
id name length Q1_a Q2_a Q1_b Q2_b
0 1 NaN l1 11.0 111.0 NaN NaN
3 1 one l1 11.0 111.0 2011.0 2011.0
9 1 one_extra l1 NaN NaN 2011.0 2011.0
1 2 two l2 22.0 222.0 2022.0 2022.0
2 3 three l3 33.0 333.0 2033.0 2033.0
6 3 NaN NaN 33.0 333.0 NaN NaN
11 3 three l3_extra NaN NaN 2033.0 2033.0
8 4 four l4 NaN NaN 2044.0 2044.0
5 5 NaN NaN 55.0 555.0 NaN NaN
7 5 five l5 NaN NaN 2055.0 2055.0
4 6 NaN l6 66.0 666.0 NaN NaN
10 7 seven l7 NaN NaN 2077.0 2077.0
我正在尝试使df_m
进入一种状态,其中根据相应NaN
列中的值填充任何id
值。每当有重复的id
时,我都希望保留两个值,以便最终得到以下df
:
id name length Q1_a Q2_a Q1_b Q2_b
0 1 one l1 11.0 111.0 2011.0 2011.0
1 1 one_extra l1 11.0 111.0 2011.0 2011.0
2 2 two l2 22.0 222.0 2022.0 2022.0
3 3 three l3 33.0 333.0 2033.0 2033.0
4 3 three l3_extra 33.0 333.0 2033.0 2033.0
5 4 four l4 NaN NaN 2044.0 2044.0
6 5 five l5 55.0 555.0 2055.0 2055.0
7 6 NaN l6 66.0 666.0 NaN NaN
8 7 seven l7 NaN NaN 2077.0 2077.0
请注意,有一些NaN
值,其中一个表中有一个条目,而另一个表中没有,例如df_a
中没有id=4
的条目,因此NaN
和Q1_a
处有Q2_a
。
以下方法可以工作,但是我想对这些代码进行矢量化处理,因为它只花了200秒以上就花了4秒钟以上的时间:
dupe_ids = pd.value_counts(df_m.id)[
pd.value_counts(df_m.id) > 1].index.values
for dupe_id in dupe_ids:
df_m.loc[df_m.id == dupe_id] = df_m.loc[df_m.id == dupe_id].ffill().bfill()
df_m = df_m.drop_duplicates().sort_values(by='id').reset_index(drop=True)
我尝试如下对代码进行矢量化处理,但是结果很奇怪(请参见id=4
)。
df_m.sort_values(by='id').groupby(
'id').ffill().bfill().drop_duplicates().reset_index(drop=True)
Output:
id name length Q1_a Q2_a Q1_b Q2_b
0 1 one l1 11.0 111.0 2011.0 2011.0
1 1 one_extra l1 11.0 111.0 2011.0 2011.0
2 2 two l2 22.0 222.0 2022.0 2022.0
3 3 three l3 33.0 333.0 2033.0 2033.0
4 3 three l3_extra 33.0 333.0 2033.0 2033.0
5 4 four l4 55.0 555.0 2044.0 2044.0
6 5 five l5 55.0 555.0 2055.0 2055.0
7 6 seven l6 66.0 666.0 2077.0 2077.0
8 7 seven l7 NaN NaN 2077.0 2077.0
我实际上试图合并的两个表要复杂得多,因此上面的示例导致的异常行为比那里看到的要多得多。有超过100列,并且不同的列可以在不同位置具有NaN
值。
任何帮助将不胜感激!
答案 0 :(得分:1)
问题是您需要同时进行ffill
和bfill
分组执行。您当前的矢量化尝试仅按组执行ffill
。
res = df_m.sort_values('id')\
.groupby('id').apply(lambda x: x.ffill().bfill())\
.drop_duplicates()
print(res)
id name length Q1_a Q2_a Q1_b Q2_b
0 1 one l1 11.0 111.0 2011.0 2011.0
9 1 one_extra l1 11.0 111.0 2011.0 2011.0
1 2 two l2 22.0 222.0 2022.0 2022.0
2 3 three l3 33.0 333.0 2033.0 2033.0
11 3 three l3_extra 33.0 333.0 2033.0 2033.0
8 4 four l4 NaN NaN 2044.0 2044.0
5 5 five l5 55.0 555.0 2055.0 2055.0
4 6 NaN l6 66.0 666.0 NaN NaN
10 7 seven l7 NaN NaN 2077.0 2077.0
答案 1 :(得分:0)
感谢jpp的回答。
为了检查一下,我在回答他的答案时将他的解决方案与该解决方案进行了计时。
Input:
df_m = df_m.append([df_m] * 10000, ignore_index=True)
%timeit df_r1 = df_m\
.groupby('id').apply(lambda x: x.ffill().bfill())\
.drop_duplicates()
%timeit df_r2 = df_m.groupby('id').ffill().groupby('id').bfill().drop_duplicates()
Output:
114 ms ± 1.26 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
112 ms ± 515 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
因此,似乎有100,000行非常关闭。