Поиск последовательных дат в кадре данных, сгруппированных по значению другого столбца - PullRequest
1 голос
/ 06 марта 2020

Таким образом, дело в том, чтобы найти человека, который вошел в 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

Ответы [ 2 ]

0 голосов
/ 06 марта 2020

Если даты и время отсортированы, а ожидаемый результат - только проверить, используют ли 3 последовательные даты в днях шаги в пользовательской функции в GroupBy.apply:

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
0 голосов
/ 06 марта 2020

Попробуйте следующий код:

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']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...