在 Pandas 中创建数据透视表并同时对每周的日期进行分组

tha*_*sdr 5 python pandas pandas-groupby

我想pd.pivot_tablepython其中一列是datetime对象的地方创建一个,但我也想每周对我的结果进行分组。这是一个简单的例子:我有以下内容DataFrame

import pandas as pd

names = ['a', 'b', 'c', 'd'] * 7
dates = ['2017-01-11', '2017-01-08', '2017-01-14', '2017-01-05', '2017-01-10', '2017-01-13', '2017-01-02', '2017-01-12', '2017-01-10', '2017-01-05', '2017-01-01', '2017-01-04', '2017-01-11', '2017-01-14', '2017-01-05', '2017-01-06', '2017-01-14', '2017-01-11', '2017-01-06', '2017-01-05', '2017-01-08', '2017-01-10', '2017-01-07', '2017-01-04', '2017-01-02', '2017-01-04', '2017-01-01', '2017-01-12']
dates = [pd.to_datetime(i).date() for i in dates]
numbers = [4, 3, 2, 1 ] * 7
data = {'name': names , 'date': dates, 'number': numbers}

df = pd.DataFrame(data)
Run Code Online (Sandbox Code Playgroud)

产生:

          date name  number
0   2017-01-11    a       4
1   2017-01-08    b       3
2   2017-01-14    c       2
3   2017-01-05    d       1
4   2017-01-10    a       4
5   2017-01-13    b       3
6   2017-01-02    c       2
7   2017-01-12    d       1
8   2017-01-10    a       4
9   2017-01-05    b       3
10  2017-01-01    c       2
11  2017-01-04    d       1
12  2017-01-11    a       4
13  2017-01-14    b       3
14  2017-01-05    c       2
15  2017-01-06    d       1
16  2017-01-14    a       4
17  2017-01-11    b       3
18  2017-01-06    c       2
19  2017-01-05    d       1
20  2017-01-08    a       4
21  2017-01-10    b       3
22  2017-01-07    c       2
23  2017-01-04    d       1
24  2017-01-02    a       4
25  2017-01-04    b       3
26  2017-01-01    c       2
27  2017-01-12    d       1
Run Code Online (Sandbox Code Playgroud)

我想创建一个数据透视表,其中行将是名称,列将是每周的日期,数字将是数字列的总和。例如,数据透视表的第一行将是:

2017-01-01 2017-01-08 2017-01-15 ... a 4 24 0

我正在做的是:

pd.pivot_table(data=df, values='number', columns=pd.Grouper(key='date', freq='1W'), index='name', aggfunc=sum)

但我收到错误: TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, but got an instance of 'RangeIndex'.

我该怎么做?我不知道是否可以将日期用作索引,因为所有日期值都不是唯一的。

Max*_*axU 5

IUC:

首先确保该date列是datetimedtype:

df['date'] = pd.to_datetime(df['date'], errors='coerce')
Run Code Online (Sandbox Code Playgroud)

然后你可以分组,求和和解压:

In [289]: (df.groupby(['name', pd.Grouper(freq='W', key='date')])
             ['number']
             .sum()
             .unstack(fill_value=0))
Out[289]:
date  2017-01-01  2017-01-08  2017-01-15
name
a              0           8          20
b              0           9          12
c              4           8           2
d              0           5           2
Run Code Online (Sandbox Code Playgroud)

由@thanasissdr 提出

In [328]: (df.groupby(['name', pd.Grouper(freq='W', key='date', closed='left')])
             ['number']
             .sum()
             .unstack(fill_value=0))
Out[328]:
date  2017-01-08  2017-01-15
name
a              4          24
b              6          15
c             12           2
d              5           2
Run Code Online (Sandbox Code Playgroud)

或者

In [330]: (df.assign(date=df['date']-pd.offsets.Day(7))
     ...:    .groupby(['name', pd.Grouper(freq='W', key='date', closed='left')])
     ...:    ['number']
     ...:    .sum()
     ...:    .unstack(fill_value=0))
     ...:
Out[330]:
date  2017-01-01  2017-01-08
name
a              4          24
b              6          15
c             12           2
d              5           2
Run Code Online (Sandbox Code Playgroud)