下面的数据表是每日级别(不是数据点之间的常规间隙),我希望将其转换为python中的每周级别(从给定日期开始,每7天滚动数据一次)。数据表如下所示:
ID Date Value
1 8/9/2018 2857
1 8/15/2018 2194
1 8/23/2018 226
1 8/30/2018 685
- ---- --
2 8/6/2018 1390
2 8/17/2018 1162
2 8/27/2018 6320
2 8/30/2018 1150所需产出如下:
Data rolling starts from 1st Jul'2018
ID Period Value
1 8/1/2018-8/7/2018 0
1 8/8/2018-8/14/2018 2857
1 8/15/2018-8/21/2018 2194
- ---------------- --
2 8/1/2018-8/7/2018 1390
2 8/8/2018-8/14/2018 0
2 8/15/2018-8/21/2018 1162
- ---------------- -
till 31st Jul'2020.发布于 2021-04-26 11:38:46
似乎您正在将Period和Value (同一周的和)分组在同一个ID下。因此,如果不按ID分组,解决方案就无法工作。
从你的数据中可以看出,每个月的分周都不会在任何星期天或星期一开始,但是每周从每月的第1、8、15、22、29周开始。因此,我们必须为这样的一周范围特别裁剪。
我们可以这样做:
df['Date1'] = pd.to_datetime(df['Date'])
df['week_start'] = df['Date1'] - pd.to_timedelta((df['Date1'].dt.day - 1) % 7, unit='d')
df['week_finish'] = df['week_start'] + pd.Timedelta('6D')
df['Period'] = df['week_start'].dt.strftime('%m/%d/%Y').astype(str) + '-' + df['week_finish'].dt.strftime('%m/%d/%Y').astype(str)
df.groupby(['ID', 'week_start', 'Period'])['Value'].sum().reset_index([0,2]).reset_index(drop=True)演示
Test Data Construction由于您的示例数据无法测试同一周的两个条目的求和条件,我使用ID等于3添加了新数据,如下所示:
data = {'ID': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
'Date': ['8/9/2018',
'8/15/2018',
'8/23/2018',
'8/30/2018',
'8/6/2018',
'8/17/2018',
'8/27/2018',
'8/30/2018',
'8/6/2018',
'8/7/2018',
'8/27/2018',
'8/28/2018'],
'Value': [2857,
2194,
226,
685,
1390,
1162,
6320,
1150,
1000,
2000,
6320,
1150]}
df = pd.DataFrame(data)
print(df)
ID Date Value
0 1 8/9/2018 2857
1 1 8/15/2018 2194
2 1 8/23/2018 226
3 1 8/30/2018 685
4 2 8/6/2018 1390
5 2 8/17/2018 1162
6 2 8/27/2018 6320
7 2 8/30/2018 1150
8 3 8/6/2018 1000
9 3 8/7/2018 2000
10 3 8/27/2018 6320
11 3 8/28/2018 1150运行新代码
df['Date1'] = pd.to_datetime(df['Date'])
df['week_start'] = df['Date1'] - pd.to_timedelta((df['Date1'].dt.day - 1) % 7, unit='d')
df['week_finish'] = df['week_start'] + pd.Timedelta('6D')
df['Period'] = df['week_start'].dt.strftime('%m/%d/%Y').astype(str) + '-' + df['week_finish'].dt.strftime('%m/%d/%Y').astype(str)
df.groupby(['ID', 'week_start', 'Period'])['Value'].sum().reset_index([0,2]).reset_index(drop=True)输出
ID Period Value
0 1 08/08/2018-08/14/2018 2857
1 1 08/15/2018-08/21/2018 2194
2 1 08/22/2018-08/28/2018 226
3 1 08/29/2018-09/04/2018 685
4 2 08/01/2018-08/07/2018 1390
5 2 08/15/2018-08/21/2018 1162
6 2 08/22/2018-08/28/2018 6320
7 2 08/29/2018-09/04/2018 1150
8 3 08/01/2018-08/07/2018 3000
9 3 08/22/2018-08/28/2018 7470注意,输出与您想要的输出略有不同,即使没有值,每周都应该显示0值。为了支持这一点,代码将更加复杂。您现在已经可以看到按ID和星期按正确的日历顺序分组的值(日期的排序顺序由临时字段week_start保证,该字段采用YYYY DD格式,以便保护按时间顺序排序的顺序。按照Period顺序进行排序将导致不同年份的同一个月一起排序,从而破坏了时间顺序。
编辑
如果周数相对于2018-08-01,而不是每个月的第一天,我们可以修改行设置df['week_start'],如下所示:
df['week_start'] = df['Date1'] - pd.to_timedelta((df['Date1'] - pd.Timestamp('2018-08-01')).dt.days % 7, unit='d')试验运行
ID等于3现在定在2018年9月。
data = {'ID': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
'Date': ['8/9/2018',
'8/15/2018',
'8/23/2018',
'8/30/2018',
'8/6/2018',
'8/17/2018',
'8/27/2018',
'8/30/2018',
'9/6/2018',
'9/7/2018',
'9/27/2018',
'9/28/2018'],
'Value': [2857,
2194,
226,
685,
1390,
1162,
6320,
1150,
1000,
2000,
6320,
1150]}
df = pd.DataFrame(data)
print(df)
ID Date Value
0 1 8/9/2018 2857
1 1 8/15/2018 2194
2 1 8/23/2018 226
3 1 8/30/2018 685
4 2 8/6/2018 1390
5 2 8/17/2018 1162
6 2 8/27/2018 6320
7 2 8/30/2018 1150
8 3 9/6/2018 1000
9 3 9/7/2018 2000
10 3 9/27/2018 6320
11 3 9/28/2018 1150运行新代码:
df['Date1'] = pd.to_datetime(df['Date'])
df['week_start'] = df['Date1'] - pd.to_timedelta((df['Date1'] - pd.Timestamp('2018-08-01')).dt.days % 7, unit='d')
df['week_finish'] = df['week_start'] + pd.Timedelta('6D')
df['Period'] = df['week_start'].dt.strftime('%m/%d/%Y').astype(str) + '-' + df['week_finish'].dt.strftime('%m/%d/%Y').astype(str)
df.groupby(['ID', 'week_start', 'Period'])['Value'].sum().reset_index([0,2]).reset_index(drop=True)输出
ID Period Value
0 1 08/08/2018-08/14/2018 2857
1 1 08/15/2018-08/21/2018 2194
2 1 08/22/2018-08/28/2018 226
3 1 08/29/2018-09/04/2018 685
4 2 08/01/2018-08/07/2018 1390
5 2 08/15/2018-08/21/2018 1162
6 2 08/22/2018-08/28/2018 6320
7 2 08/29/2018-09/04/2018 1150
8 3 09/05/2018-09/11/2018 3000
9 3 09/26/2018-10/02/2018 7470发布于 2021-04-26 08:21:15
试试这个:
def get_week(x,start_date):
return ((x.date()-start_date.date()).days)//7
df['formatted_date'] = pd.to_datetime(df['date'])
start_date = pd.to_datetime('Add your start date')
df["week"] = df["formatted_date"].apply(lambda x:get_week(x,start_date))
df["year"] = df.formatted_date.apply(lambda x: x.year)
df.groupby(['week','year']).sum() 发布于 2021-04-26 09:02:05
使用groupby()方法。确保值为数字(int,浮动而不是对象)
date value
0 2018-08-09 2857
1 2018-08-15 2194
2 2018-08-23 226
3 2018-08-30 685
4 2018-08-06 1390
5 2018-08-17 1162
6 2018-08-27 6320
7 2018-08-30 1150
>>> df['week']=df['date'].transform(lambda x: x.week)
>>> df.groupby('week').sum()
value
week
32 4247
33 3356
34 226
35 8155https://stackoverflow.com/questions/67262520
复制相似问题