以下是我拥有的数据框
score_df
col1_id col2_id score
1 2 10
5 6 20
records_df
date col_id
D1 6
D2 4
D3 1
D4 2
D5 5
D6 7
我想根据以下标准计算分数:
当2在1之后出现时,分数应指定为10,或者当1在2之后出现时,分数应分配为10。
即,当(1,2)的得分为10 ..(2,1)时,得分也为10。
考虑(1,2)。第一次出现1时,我们不分配分数。我们标记该行并等待2发生。当该列中出现2时,我们给分数10。
考虑(2,1)。当2首先出现时。我们指定值0,然后等待1出现。当出现1时,我们给分数10。
所以,第一次-不要分配分数,等待相应的事件发生,然后分配分数
因此,我的结果数据框应如下所示
结果
date col_id score
D1 6 0 -- Eventhough 6 is there in score list, it occured for first time. So 0
D2 4 0 -- 4 is not even there in list
D3 1 0 -- 1 occurred for first time . So 0
D4 2 10 -- 1 occurred previously. 2 occurred now.. we can assign 10.
D5 5 20 -- 6 occurred previously. we can assign 20
D6 7 0 -- 7 is not in the list
我在score_df和record_df中都有大约10万行。循环和分配分数很费时间。有人可以在不循环整个数据帧的情况下提供逻辑帮助吗?
答案 0 :(得分:2)
据我了解,您可以尝试melt
进行取消透视,然后尝试merge
。保持索引与融化的df相同,我们检查where
的索引为duplicated
,然后从合并返回0。
m = score_df.reset_index().melt(['index','uid','score'],
var_name='col_name',value_name='col_id')
final = records_df.merge(m.drop('col_name',1),on=['uid','col_id'],how='left')
c = final.duplicated(['index']) & final['index'].notna()
final = final.drop('index',1).assign(score=lambda x: x['score'].where(c,0))
print(final)
uid date col_id score
0 123 D1 6 0.0
1 123 D2 4 0.0
2 123 D3 1 0.0
3 123 D4 2 10.0
4 123 D5 5 20.0
5 123 D6 7 0.0