在我的数据框df1
中,我想在每个组的第一个行中为val1
分配一个新值。新值取决于组,并存储在df2
。
import pandas as pd
df1 = pd.DataFrame({'group': list('aaabbb'), 'val1': [2, 3, 6, 3, 7, 10]})
print df1
# group val1
#0 a 2
#1 a 3
#2 a 6
#3 b 3
#4 b 7
#5 b 10
df2 = pd.DataFrame({'group': ['a', 'b'], 'val2': [1, 2]})
print df2
# group val2
#0 a 1
#1 b 2
# Desired Output:
# group val1
#0 a 1 <- updated
#1 a 3
#2 a 6
#3 b 2 <- updated
#4 b 7
#5 b 10
我的第一个解决方案是合并两个数据框,并使用自定义函数将val2
分配给第一行中的val1
,如此post中所述。这有效,但速度很慢,内存使用率很高:
df3 = pd.merge(df1, df2, on='group')
def set_first_value(group):
group['val1'].iat[0] = group['val2'].iat[0]
return group
df3.groupby('group').apply(set_first_value)
df3 = pd.merge(df1, df2, on='group')
是否有更有效的方法来更改每个组中第一个元素的值?
答案 0 :(得分:1)
我在撰写这篇文章时提出了一个更好的解决方案,速度提高了10倍。它使用groupby.first()
以下是基准:
# setup
import pandas as pd
import numpy as np
n = 100000
m = 100
df1 = pd.DataFrame({'group': range(n)*m, 'val1': range(n*m)})
df2 = pd.DataFrame({'group': range(n), 'val2': np.random.randint(1,100, size=n)})
使用客户功能的较慢方法:
%%time
df3 = pd.merge(df1, df2, on='group')
def set_first_value(group):
group['val1'].iloc[0] = group['val2'].iloc[0]
return group
df3.groupby('group').apply(set_first_value)
CPU时间:用户55.9秒,系统:2.81秒,总计:58.7秒 壁挂时间:59.8秒
使用groupby.first()的更快方法:
%%time
df3 = pd.merge(df1, df2, on='group')
df3['ix'] = df3.index
ix_first = df3.groupby('group').first()['ix']
df3['val1'] = df3['val2'].where(df3['ix'].isin(ix_first), df3['val1'])
CPU时间:用户3.41秒,系统:1.2秒,总计:4.62秒 壁挂时间:4.78秒