首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何根据熊猫的每日数据制作每周一次的时间序列

如何根据熊猫的每日数据制作每周一次的时间序列
EN

Stack Overflow用户
提问于 2021-04-26 07:31:20
回答 3查看 1.4K关注 0票数 1

下面的数据表是每日级别(不是数据点之间的常规间隙),我希望将其转换为python中的每周级别(从给定日期开始,每7天滚动数据一次)。数据表如下所示:

代码语言:javascript
运行
复制
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

所需产出如下:

代码语言:javascript
运行
复制
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.
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-04-26 11:38:46

似乎您正在将PeriodValue (同一周的和)分组在同一个ID下。因此,如果不按ID分组,解决方案就无法工作。

从你的数据中可以看出,每个月的分周都不会在任何星期天或星期一开始,但是每周从每月的第1、8、15、22、29周开始。因此,我们必须为这样的一周范围特别裁剪。

我们可以这样做:

代码语言:javascript
运行
复制
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添加了新数据,如下所示:

代码语言:javascript
运行
复制
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

运行新代码

代码语言:javascript
运行
复制
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)

输出

代码语言:javascript
运行
复制
   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'],如下所示:

代码语言:javascript
运行
复制
df['week_start'] = df['Date1'] - pd.to_timedelta((df['Date1'] - pd.Timestamp('2018-08-01')).dt.days % 7, unit='d')

试验运行

ID等于3现在定在2018年9月。

代码语言:javascript
运行
复制
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

运行新代码:

代码语言:javascript
运行
复制
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)

输出

代码语言:javascript
运行
复制
   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
票数 1
EN

Stack Overflow用户

发布于 2021-04-26 08:21:15

试试这个:

代码语言:javascript
运行
复制
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() 
票数 0
EN

Stack Overflow用户

发布于 2021-04-26 09:02:05

使用groupby()方法。确保值为数字(int,浮动而不是对象)

代码语言:javascript
运行
复制
        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     8155
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67262520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档