有效地创建频次和新近度列

时间:2019-03-27 15:44:33

标签: python python-3.x pandas dictionary

这是一个非常具体的问题-我的代码很慢,想知道我做错了什么还是有更好的方法。

情况:我有两个数据框,框架和联系人。框架是一个人的数据库,联系人是与这些人的联系点。它们看起来像:

框架:

       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分钟-我觉得必须有一个更有效的方法来做到这一点(将来我会需要它)。任何想法将不胜感激-谢谢!

1 个答案:

答案 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