以下是我拥有的数据帧
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万行。循环和分配分数需要时间。有人能在不循环整个数据帧的情况下帮助实现逻辑吗?
根据我的理解,您可以尝试melt
来取消象牙,然后尝试merge
。从熔化的df中保留索引,我们检查where
,索引是duplicated
,然后从合并返回分数else 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