选择ID(以7天为增量)

时间:2019-03-07 04:08:30

标签: python pandas data-processing

我是python和pandas的新手,正在研究一个3个月的数据的pandas数据框,如下所示:

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天为增量选择ID,这样,如果从上次选择日期起的接下来的7天中没有ID,则它不会选择任何ID。生成的数据框看起来像这样

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 个答案:

答案 0 :(得分:2)

使用@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. calculate the time differenceDate之间(每个ID
  2. 计算星期(0-7天是第1周,7-14天是第2周,依此类推)

然后,在每个组中(使用groupby),use这2个辅助函数来计算时间和星期。由于您只需要每周(7天)的第一条记录,因此再进行一次groupby并检索第一条记录。

这是用于将时间和星期作为单独的列计算的代码

  • 用于计算num_weeks的代码来自于此SO post
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

原始尝试

Generate some data与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

答案 1 :(得分:0)

执行以下操作:

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