Je suis très nouveau sur python et pandas et je travaille sur une trame de données pandas qui est une donnée de 3 mois et ressemble à:

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

Ce que j'essaie de faire, c'est de sélectionner les ID uniquement par incrément de 7 jours, de sorte qu'il ne sélectionne aucun ID s'il est présent pendant les sept prochains jours à compter de la dernière date de sélection. Le bloc de données résultant ressemblerait à ceci

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

J'ai essayé depuis le matin et toute aide serait très appréciée

Merci beaucoup d'avance!!

0
Analytics_TM 7 mars 2019 à 07:08

2 réponses

Meilleure réponse

Utilisez les données de @suicidalteddy, avec des modifications mineures

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

Maintenant, utilisez une fonction d'assistance pour

  1. calculer le décalage horaire entre Dates (par ID)
  2. calculer la semaine (0-7 jours est la semaine 1, 7-14 jours est la semaine 2, etc.)

Ensuite, au sein de chaque groupe (utilisez groupby), utilisez ces 2 fonctions d'aide pour calculer l'heure et la semaine. Puisque vous n'avez besoin que de la première entrée de chaque semaine (7 jours), effectuez un deuxième groupby et récupérez le premier enregistrement.

Voici le code pour calculer l'heure et la semaine sous forme de colonnes séparées

  • le code pour calculer num_weeks provient de ce poste SO
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)

Voici le résultat de l'étape ci-dessus

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

Maintenant, le deuxième groupby et triez pour obtenir le résultat final souhaité

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

Tentative d'origine

Générer des données dans le même format que 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

Utilisez pd.data_range pour choisir dehors seulement les intervalles requis

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
2
edesz 12 mars 2019 à 04:41

Faites ceci:

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

Résultat:

        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
0
entropy 7 mars 2019 à 10:36