【问题标题】:How to resample a column by id如何按 id 重新采样列
【发布时间】:2019-08-29 00:16:44
【问题描述】:

我有一个像这样的数据集:

id    date    value

1   16-12-1     9
1   16-12-1     8
1   17-1-1      18
2   17-3-4      19
2   17-3-4      20
1   17-4-3      21
2   17-7-13     12
3   17-8-9      12
2   17-9-12     11
1   17-11-12    19
3   17-11-12    21

上面唯一的结构是行是按日期排序的。

我想要做的是,按 id 分组并重新采样日期,以便每个 id 具有相同的数值。每月、每周或每天重新采样就足够了。

我的最终数据集(每年重采样)如下所示:

id    interval           value

1   16-12-1 - 17-12-1     75
2   16-12-1 - 17-12-1     62
3   16-12-1 - 17-12-1     33

如何实现?这会起作用吗(因为我在日期字段中没有秒数,即它不是标准的 pandas 日期时间对象)?

dataframe.groupby(id).resample('year')

有没有更快的方法来做到这一点?

【问题讨论】:

  • 您似乎正在寻找interval 列中的最小和最大日期。 value 列来自标准 GROUP BY。您能否解释重新采样必须完成的工作?即您需要在interval 列中提供哪些信息?
  • @edesz 谢谢,就像上面的最终数据集快照一样,所有 id 的间隔都是相同的,例如[16-12-1 - 17-12-1] 适合所有人。重采样以每周间隔对值进行分组。因此,通过重新采样,我打算为每个 id 具有相同数量的值。重采样将在间隔列的最大和最小日期之间,以使每个 id 具有相同数量的值。

标签: python pandas dataframe time-series pandas-groupby


【解决方案1】:

更新尝试(重新采样)

生成数据

d = [['id', 'date', 'value'],
    [1, '2016-12-1', 9],
    [1, '2016-12-1',8],
    [1, '2017-1-1',18],
    [2, '2017-3-4',19],
    [2, '2017-3-4',20],
    [1,'2017-4-3',21],
    [2, '2017-7-13',12],
    [3, '2017-8-9',12],
    [2, '2017-9-12',11],
    [1, '2017-11-12',19],
    [3, '2017-11-12',21],]
df = pd.DataFrame(d[1:], columns=d[0])

print(df)
    id        date  value
0    1   2016-12-1      9
1    1   2016-12-1      8
2    1    2017-1-1     18
3    2    2017-3-4     19
4    2    2017-3-4     20
5    1    2017-4-3     21
6    2   2017-7-13     12
7    3    2017-8-9     12
8    2   2017-9-12     11
9    1  2017-11-12     19
10   3  2017-11-12     21

每年重新抽样,然后是总和

df.index = pd.to_datetime(df.date)
df.drop('date',axis = 1, inplace = True)
df_g = df.groupby('id').resample('y').sum()
df_g.drop(columns=['id'], inplace=True)

print(df_g)
               value
id date             
1  2016-12-31     17
   2017-12-31     58
2  2017-12-31     62
3  2017-12-31     33

初始答案(无需重新采样)

您可以这样做,但它不会执行明确的resample 操作

f = {'date':['min','max'],
    'value':'sum'}
df_grouped = df.groupby(['id']).agg(f)
df_grouped.columns = ['_'.join(col) for col in df_grouped.columns.values]
df_grouped.reset_index(drop=False, inplace=True)

print(df_grouped)
   id  date_min date_max  value_sum
0   1   16-12-1   17-4-3         75
1   2    17-3-4  17-9-12         62
2   3  17-11-12   17-8-9         33

【讨论】:

  • 谢谢,但它并没有像你说的那样重新采样,而且不同的 id 有不同的间隔。请查看对您的评论的回复。谢谢。
【解决方案2】:

每周按 id 求和:

df['date'] = pd.to_datetime(df['date'], format='%y-%m-%d')
df = df.set_index('date')
df.groupby('id').resample('W')['value'].agg('sum').loc[lambda x: x>0]

输出:

id  date      
1   2016-12-04    17
    2017-01-01    18
    2017-04-09    21
    2017-11-12    19
2   2017-03-05    39
    2017-07-16    12
    2017-09-17    11
3   2017-08-13    12
    2017-11-12    21
Name: value, dtype: int64

【讨论】:

  • 谢谢,pd.to_datetime 会直接使用这种日期格式吗?我早些时候尝试过,但没有奏效。上面示例中的日期看起来也有误,例如16-12-1 应该是 2016 - 12 - 1 ,年 - 月 - 日期
  • 那么您的数据中有一些错误的日期......您可以使用 errors='coerce' 来获取所有错误数据的空值。
  • 您也可以使用 format 来明确定义要在 pd.to_datetime 中使用的格式。事实上,如果您确实定义了格式,它将执行得更快。
  • 谢谢,也是先设置索引再转日期时间会更快吗?
  • 代码很慢,一百万行需要5个小时,有什么方法可以加快速度吗?
猜你喜欢
  • 2015-04-10
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
  • 2019-01-18
  • 2019-04-15
  • 2022-01-05
  • 1970-01-01
  • 2023-04-01
相关资源
最近更新 更多