这是一个非常具体的问题-我的代码很慢,想知道我做错了什么还是有更好的方法。
情况:我有两个数据框,框架和联系人。框架是一个人的数据库,联系人是与这些人的联系点。它们看起来像:
框架:
name
id
166 Bob
253 Serge
1623 Anna
766 Benna
981 Paul
联系人:
id type date
0 253 email 2016-01-05
1 1623 sale 2012-05-12
2 1623 email 2017-12-22
3 253 sale 2018-02-15
我想在框架中添加两列,“ most_recent”和“ 3年联系计数”,以提供最近的联系(如果有)和过去3年的联系数量。
(框架为〜100,000行,联系人为〜95,000)
到目前为止,我减少了要遍历的id的数量,然后为每个id创建具有正确值的字典:
id_list = [i for i in frame.index if i in contacts['id']]
freq_rec_dict = {i: [contacts.loc[contacts['id']==i,'value'].max(),
len(contacts.loc[(contacts['id']==i)&(contacts['value']>dt(2016,1,1))])]
for i in id_list}
然后,我将字典转换为数据框并执行连接:
freq_rec_df = pd.DataFrame.from_dict(freq_rec_dict, orient='index',columns=['most_recent','3 year contact count'])
result = frame.join(freq_rec_df)
这确实满足了我的需求,但是字典理解却花了30分钟-我觉得必须有一个更有效的方法来做到这一点(将来我会需要它)。任何想法将不胜感激-谢谢!
答案 0 :(得分:1)
您没有指定输出,但是可以了。您应该利用内置的groupby
方法,而不是将数据从框架中取出并重新放入框架中,然后合并
contacts.groupby('id')[['date','type']].max()
date type
id
253 2018-02-15 sale
1623 2017-12-22 sale
如果需要节省内存空间,可以一行执行。同样,您不提供首选输出,因此我使用了左连接。您还可以使用'inner'
仅保留记录所在的行。
df=pd.merge(frame,contacts.groupby('id')[['date','type']].max(), left_index=True, right_index=True, how='left')
name date type
id
166 Bob NaN NaN
253 Serge 2018-02-15 sale
1623 Anna 2017-12-22 sale
766 Benna NaN NaN
981 Paul NaN NaN