如何在 Python 中创建日期时间使用跟踪器?

How to create a date time usage tracker in Python?

我正在尝试创建一个使用跟踪器来标记在最后一次标记 ID 后 14 天内具有相同 ID 的项目。因此,如果相同的 ID 在第一个 ID 没有标记后的 14 天内出现,如果它在第一个标记后的 14 天之外出现,那么它将成为每个 ID 的第二个标记。

我试过使用 .ffill() .groupby .rolling 这些有助于在 14 天内找到重复项,但对滚动标志没有帮助。我认为解决方案可能在于 for 循环的某个时间和扩展的 window?

起始码

df:
date     id
1/1/19      38
1/5/19      16
1/10/19     38 
1/15/19     38
1/21/19     38
1/30/19     16
2/2/19      38
2/2/19      38
2/3/19      38

我需要得到什么

df2:
date     id       flag    most recent flag
1/1/19      38     True        1/1/19
1/5/19      16     True        1/5/19  
1/10/19     38     False       1/1/19
1/15/19     38     True        1/15/19
1/21/19     38     False       1/15/19
1/30/19     16     True        1/30/19 
2/2/19      38     True        2/2/19   
2/2/19      38     False       2/2/19   
2/3/19      38     False       2/2/19

这种问题很复杂,因为标记取决于最后一个,可以是之前的任意行数。我认为您需要创建自己的函数来获取每组 id 的 True,但首先要确保日期列是日期时间。然后你可以这样做:

df.date = pd.to_datetime(df.date)

def create_flag(x, nb_days = 14):
    # calculate the delta in days with the first value
    arr = (x - x.min()).dt.days.values
    # create an array to get the flags
    flag = np.zeros_like(arr, dtype=bool)
    # change the first value
    flag[0] = True
    # iterate over the all data
    for i in range(1, len(arr)):
        # once over xx days
        if arr[i] >= nb_days:
            #remove this value to the rest of the arr to restart the count from this flag
            arr[i:] -= arr[i]
            # add the flag to true 
            flag[i] = True
    return pd.DataFrame( {'flag':flag, 'last_flag': x[flag]}, # mask x with flag to get the date of flagging
                         index=x.index).ffill()  # ffill for the date
df[['flag','last_flag']] = df.groupby('id').date.apply(create_flag)
print (df)
        date  id   flag  last_flag
0 2019-01-01  38   True 2019-01-01
1 2019-01-05  16   True 2019-01-05
2 2019-01-10  38  False 2019-01-01
3 2019-01-15  38   True 2019-01-15
4 2019-01-21  38  False 2019-01-15
5 2019-01-30  16   True 2019-01-30
6 2019-02-02  38   True 2019-02-02
7 2019-02-02  38  False 2019-02-02
8 2019-02-03  38  False 2019-02-02

抱歉让您久等了

这里是生成df的代码如上图

df = pd.DataFrame({
'date':['1/1/19','1/5/19','1/10/19','1/15/19','1/21/19','1/30/19','2/2/19','2/2/19','2/3/19'], 
'id':[38,16,38,38,38,16,38,38,38]
})
df['date'] = pd.to_datetime(df['date'])

而且,这些是我在计算您的标志之前创建的其他列

df['days_ago'] = df.groupby('id')['date'].diff()\
.fillna(pd.Timedelta(seconds=0)).astype('timedelta64[D]').astype(int)
df['days_ago_cumsum'] = df.groupby('id')['days_ago'].cumsum()

而且,这是计算那个标志的函数

def get_fixed_day_flag(days_ago_cumsum, within=14):
while True:
    cond = days_ago_cumsum >= within
    days_ago_cumsum_min = days_ago_cumsum.where(cond).min()
    new_days_ago_cumsum = days_ago_cumsum.where(cond) - days_ago_cumsum_min

    cond = new_days_ago_cumsum.notna()
    days_ago_cumsum[cond] = new_days_ago_cumsum[cond].astype(int)

    if days_ago_cumsum.max() < within:
        return days_ago_cumsum == 0

然后,完成这两行

df['flag'] = df.groupby('id')['days_ago_cumsum'].transform(get_fixed_day_flag)
df['flag'] = df['flag'] & ~df.duplicated(subset=['date','id'])