首页 > 解决方案 > Pandas 数据框列值取决于动态行数

问题描述

我有一个看起来像这样的数据框:

用户 当前的日期 之前的日期 points_scored
1 2021-01-01 2020-10-01 5
2 2021-01-01 2020-10-01 4
2 2021-01-21 2020-10-21 4
2 2021-05-01 2021-02-01 4

prior_date列很简单current_date - 3 monthspoints_scored是在 上得分的点数current_date。我希望能够识别sum(points_scored) >= 8给定user的行在哪里,考虑的行将current_date是在current_date和之间的位置prior_date。保证没有单行的值为points_scored >= 8.

例如,在上面的示例中,我希望返回如下内容:

用户 当前的日期 之前的日期 points_scored 旗帜
1 2021-01-01 2021-04-01 5 0
2 2021-01-01 2020-10-01 4 0
2 2021-01-21 2020-10-21 4 1
2 2021-05-01 2021-02-01 4 0

第三行显示flag=1,因为对于第 3 行的值current_date=2021-01-21prior_date=2020-10-21,要考虑的行将是第 2 行和第 3 行。我们考虑第 2 行current_date=2021-01-01,因为第 2 行介于第 3 行current_date和之间prior_date

最终,我想最终得到一个显示不同用户和标志的数据结构。它可以是数据框或字典——任何容易引用的东西。

用户 旗帜
1 0
2 1

为此,我正在做这样的事情:

flags = {}
ids = list(df['user'].value_counts()[df['user'].value_counts() > 2].index)
for id in ids:
    temp_df = df[df['user'] == id]
    for idx, row in temp_df.iterrows():
        cur_date = row['current_date']
        prior_date = row['prior_date']
        temp_total = temp_df[(temp_df['current_date'] <= cur_date) & (cand_df['current_date'] >= prior_date)]['points_scored'].sum()
        if temp_total >= 8:
            flags[id] = 1
            break

上面的代码有效,但实际执行时间太长了。

标签: pythonpandasdataframe

解决方案


你是对的,对大数据执行循环可能非常耗时。这就是 numpy 的力量发挥最大作用的地方。我仍然不确定你想要什么,但我可以帮助解决 Numpy.select 可以有效地执行你的 if else 语句的速度。

import pandas as pd 
import numpy as np

condition = [df['points_scored']==5, df['points_scored']==4, df['points_scored'] ==3] # <-- put your condition here
choices = ['okay', 'hmmm!', 'yes'] #<--what you want returned (the order is important)
np.select(condition,choices,default= 'default value')

此外,您可能想要更简洁地表达您想要的内容。同时你可以用 np.select() 重构你的循环


推荐阅读