Выберите идентификаторы с шагом 7 дней - PullRequest
0 голосов
/ 07 марта 2019

Я очень новичок в python и pandas и работаю над фреймом данных pandas, который представляет собой данные за 3 месяца и выглядит как:

Date     ID   product
Jul-1     1     A
Jul-1     2     B
Jul-1     3     D
Jul-4     2     F
Jul-5     1     G
Jul-9     1     K
Jul-9     2     L
Jul-9     3     X
Jul-11    1     N
Jul-13    3     M
Jul-17    1     Z
Jul-17    2     O
Jul-17    3     T

То, что я пытаюсь сделать, - это выбирать идентификаторы только с шагом 7 дней, чтобы он не выбирал никаких идентификаторов, если они присутствуют в течение следующих семи дней с последней даты, когда они были выбраны. Результирующий кадр данных будет выглядеть следующим образом

Date     ID   product
Jul-1     1     A
Jul-1     2     B
Jul-1     3     D
Jul-9     1     K
Jul-9     2     L
Jul-9     3     X
Jul-17    1     Z
Jul-17    2     O
Jul-17    3     T

Стараюсь с утра, и любая помощь будет высоко оценена

Заранее большое спасибо !!

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Использовать данные из @suicidalteddy, с незначительными правками

import numpy as np
import panas as pd

dat = pd.DataFrame([{'Date': '07/01/2016', 'ID': 1, 'product':'A'},
                {'Date': '07/01/2016', 'ID': 2, 'product':'B'},
                {'Date': '07/01/2016', 'ID': 3, 'product':'D'},
                {'Date': '07/04/2016', 'ID': 2, 'product':'F'},
                {'Date': '07/05/2016', 'ID': 1, 'product':'G'},
                {'Date': '07/09/2016', 'ID': 1, 'product':'K'},
                {'Date': '07/09/2016', 'ID': 2, 'product':'L'},
                {'Date': '07/09/2016', 'ID': 3, 'product':'X'},
                {'Date': '07/11/2016', 'ID': 1, 'product':'N'},
                {'Date': '07/13/2016', 'ID': 3, 'product':'M'},
                {'Date': '07/17/2016', 'ID': 1, 'product':'Z'},
                {'Date': '07/17/2016', 'ID': 2, 'product':'O'},
                {'Date': '07/17/2016', 'ID': 3, 'product':'T'},])
dat.Date = pd.to_datetime(dat.Date, format="%m/%d/%Y")

print(dat)
         Date  ID product
0  2016-07-01   1       A
1  2016-07-01   2       B
2  2016-07-01   3       D
3  2016-07-04   2       F
4  2016-07-05   1       G
5  2016-07-09   1       K
6  2016-07-09   2       L
7  2016-07-09   3       X
8  2016-07-11   1       N
9  2016-07-13   3       M
10 2016-07-17   1       Z
11 2016-07-17   2       O
12 2016-07-17   3       T

Теперь используйте вспомогательную функцию для

  1. рассчитать разницу во времени между Date с (за ID)
  2. рассчитать неделю (0-7 дней - неделя 1, 7-14 дней - неделя 2 и т. Д.)

Затем в каждой группе (используйте groupby), используйте эти 2 вспомогательные функции для вычисления времени и недели. Поскольку вам требуется только первая запись каждой недели (7 дней), выполните вторую groupby и получите первую запись.

Вот код для расчета времени и недели в виде отдельных столбцов

  • код для вычисления num_weeks от этого ТАК
dat = dat.sort_values(by=['ID','Date'])
dat['time'] = pd.Series()
dat['week'] = pd.Series([1]*len(dat))

def calc_time(df):
    df.loc[:,'time'] = df['Date'] - df.loc[df.index.min(), 'Date']
    num_weeks = (
        int(np.ceil((dat['Date'].max() - \
            dat['Date'].min())/np.timedelta64(1, 'W')))
                )
    df = calc_week(df, num_weeks) # num_weeks = 3
    return df

def calc_week(df, num_weeks):
    for week in range(1, num_weeks+1):
        # print(str(week*7), str((week+1)*7))
        df.loc[\
            (df['time'] > str(week*7)+' days') & \
            (df['time'] <= str((week+1)*7)+' days'), \
        'week'] = week+1
    return df

dat = dat.groupby(['ID']).apply(calc_time)

Вот результат вышеприведенного шага

print(dat)
         Date  ID product    time  week
0  2016-07-01   1       A  0 days     1
4  2016-07-05   1       G  4 days     1
5  2016-07-09   1       K  8 days     2
8  2016-07-11   1       N 10 days     2
10 2016-07-17   1       Z 16 days     3
1  2016-07-01   2       B  0 days     1
3  2016-07-04   2       F  3 days     1
6  2016-07-09   2       L  8 days     2
11 2016-07-17   2       O 16 days     3
2  2016-07-01   3       D  0 days     1
7  2016-07-09   3       X  8 days     2
9  2016-07-13   3       M 12 days     2
12 2016-07-17   3       T 16 days     3

Теперь второй groupby и сортировка, чтобы получить окончательный желаемый результат

dat = dat.groupby(['ID','week']).first().reset_index(drop=False)
dff = (
    dat[['Date','ID','product']].sort_values(by=['Date','ID'])
                                .reset_index(drop=True)
    )

print(dff)
        Date  ID product
0 2016-07-01   1       A
1 2016-07-01   2       B
2 2016-07-01   3       D
3 2016-07-09   1       K
4 2016-07-09   2       L
5 2016-07-09   3       X
6 2016-07-17   1       Z
7 2016-07-17   2       O
8 2016-07-17   3       T

Исходная попытка

Генерировать некоторые данные в том же формате, что и OP

idx = pd.date_range('2018-04-01', '2018-05-01', freq='1D') + \
      pd.DateOffset(days=16)
df = pd.DataFrame(idx, columns=['Date'])
df.set_index('Date', inplace=True)
df['ID'] = range(len(idx))
df['product'] = range(12,12+len(idx))

print(df)
            ID  product
Date                   
2018-04-17   0       12
2018-04-18   1       13
...
2018-05-16  29       41
2018-05-17  30       42

Используйте pd.data_range, чтобы выбрать только необходимые интервалы

idx = pd.date_range(df.index[0], df.index[-1], freq='7D')
df_seven_days = df.loc[idx].reset_index(drop=False)
df_seven_days.rename(columns={'index': 'Date'}, inplace=True)

print(df_seven_days)
      Date  ID  product
2018-04-17   0       12
2018-04-24   7       19
2018-05-01  14       26
2018-05-08  21       33
2018-05-15  28       40
0 голосов
/ 07 марта 2019

Сделайте это:

dat = pd.DataFrame([{'Date': '01/02/2016', 'ID': 1, 'product':'A'},
                {'Date': '01/02/2016', 'ID': 2, 'product':'B'},
                {'Date': '01/04/2016', 'ID': 4, 'product':'C'},
                {'Date': '01/05/2016', 'ID': 5, 'product':'D'},
                {'Date': '01/06/2016', 'ID': 6, 'product':'a'},
                {'Date': '01/07/2016', 'ID': 7, 'product':'b'},
                {'Date': '01/09/2016', 'ID': 8, 'product':'d'},
                {'Date': '01/09/2016', 'ID': 9, 'product':'A'},
                {'Date': '01/16/2016', 'ID': 10, 'product':'B'},
                {'Date': '01/18/2016', 'ID': 11, 'product':'C'},
                {'Date': '01/18/2016', 'ID': 12, 'product':'K'},
                {'Date': '01/21/2016', 'ID': 13, 'product':'J'},
                {'Date': '01/25/2016', 'ID': 14, 'product':'I'},
                {'Date': '01/25/2016', 'ID': 15, 'product':'H'},
                {'Date': '01/25/2016', 'ID': 16, 'product':'G'},
                {'Date': '01/30/2016', 'ID': 17, 'product':'F'}]) # Replace with your data
filtered_data = pd.DataFrame(columns=['Date', 'ID', 'product'])
dat.Date = pd.to_datetime(dat.Date, format="%m/%d/%Y") # Change the format as per your data
filtered_data.loc[len(filtered_data)] = dat.iloc[0]

def trans(row):
    if (row.Date - filtered_data.tail(1).iloc[0].Date).days >= 7 or (row.Date - filtered_data.tail(1).iloc[0].Date).days == 0:
        filtered_data.loc[len(filtered_data)] = row

dat.apply(trans, axis=1)
print filtered_data

Результат:

        Date  ID product
0 2016-01-02   1       A
1 2016-01-02   1       A
2 2016-01-02   2       B
3 2016-01-09   8       d
4 2016-01-09   9       A
5 2016-01-16  10       B
6 2016-01-25  14       I
7 2016-01-25  15       H
8 2016-01-25  16       G
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...