【问题标题】:Find consecutive dates in a dataframe, grouped by another column value查找数据框中的连续日期,按另一列值分组
【发布时间】:2020-03-06 06:26:54
【问题描述】:

所以关键是要找到连续 3 个日期输入的人。 我的框架是这样的:

        DateEntry    Person
1       2018-03-18   A
2       2018-03-19   A
3       2018-03-21   A
4       2018-09-25   B
5       2018-09-26   B
6       2018-09-27   B

我知道如何检查的唯一方法是将日期更改为字符串列表,然后检查。 它工作正常,但是,这种方法是不允许的。

有没有办法通过 pandas 遍历数据框上的行来找到答案?

我只希望显示以下输出。我不需要将结果保存在数据框中。 预期输出:

Person A did not enter on 3 consecutive days.

Person B did enter on three consecutive days.
Consecutive days entered by person B:
2018-09-25
2018-09-26
2018-09-27

【问题讨论】:

  • 您的预期输出到底是什么? DateEntry 列是否总是被排序?同一个人是否总是连续出现至少三个条目?
  • 我现在对其进行了编辑以显示预期的输出。谢谢指正!
  • 每组总是有 3 个值?
  • 不一定,其他一些人,假设C和D有4-5个日期的条目。我只需要找到至少进入 3 天的人。所以 >=3。
  • 超级好,所以我的回答应该很好用。如果还需要日期时间,请寻求解决方案。

标签: python pandas dataframe date datetime


【解决方案1】:

如果对日期时间进行了排序并且预期输出仅检查是否有 3 个连续日期在 GroupBy.apply 的自定义函数中使用 strides

df['DateEntry'] = pd.to_datetime(df['DateEntry'])

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

def f(x):
    vals = rolling_window(x.to_numpy(), 3)
    dif = np.diff(vals, axis=1).astype("timedelta64[D]")==np.array([1], dtype='timedelta64[D]')
    #print (dif)

    return dif.all(axis=1).any()

s = df.groupby('Person')['DateEntry'].apply(f)
print (s)
Person
A    False
B     True
Name: DateEntry, dtype: bool

如果还需要日期时间:

print (df)
    DateEntry Person
1  2018-03-18      A
2  2018-03-19      A
3  2018-03-21      A
4  2018-08-25      B
5  2018-08-26      B
6  2018-08-27      B
7  2018-09-25      B
8  2018-09-26      B
9  2018-09-27      B
10 2018-09-30      B

df['DateEntry'] = pd.to_datetime(df['DateEntry'])
df = df.sort_values(['Person','DateEntry'])

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

def f(x):
    vals = rolling_window(x.to_numpy(), 3)
    dif = np.diff(vals, axis=1).astype("timedelta64[D]")==np.array([1], dtype='timedelta64[D]')

    return pd.DataFrame(vals[dif.all(axis=1)])

df1 = df.groupby('Person')['DateEntry'].apply(f)
print (df1)
                  0          1          2
Person                                   
B      0 2018-08-25 2018-08-26 2018-08-27
       1 2018-09-25 2018-09-26 2018-09-27

【讨论】:

    【解决方案2】:

    试试下面的代码:

    import pandas as pd
    from datetime import datetime
    
    data =[['2018-03-18', 'A'],
           ['2018-03-19', 'A'],
           ['2018-03-21', 'A'],
           ['2018-09-25', 'B'],
           ['2018-09-26', 'B'],
           ['2018-09-27', 'B']]
    df=pd.DataFrame(data, columns = ['DateEntry', 'Person'])
    
    Person = None
    Date = None
    count = 0
    for index, row in df.iterrows():
        if Person:
            if Person == row['Person']:
                count += 1
            else:
                Person = row['Person']
                Date = None
                count = 0
        else:
            Person = row['Person']
            count += 1
    
        if Date:
            if (datetime.strptime(row['DateEntry'], "%Y-%m-%d") - datetime.strptime(Date, "%Y-%m-%d")).days == 1:
                Date = row['DateEntry']
                if count == 3:
                    print('The consecutive visitor is -- {}'.format(Person))
            else:
                Person = None
                Date = None
                count = 0
        else:
            Date = row['DateEntry']
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 2021-12-06
      • 2012-05-12
      相关资源
      最近更新 更多