【问题标题】:Resampling a pandas dataframe with multi-index containing timeseries使用包含时间序列的多索引重新采样 pandas 数据帧
【发布时间】:2017-11-26 20:07:25
【问题描述】:

对于创建看似与 this question 重复的内容表示歉意。我有一个形状或多或少类似于下面的数据框:

df_lenght = 240
df = pd.DataFrame(np.random.randn(df_lenght,2), columns=['a','b'] )
df['datetime'] = pd.date_range('23/06/2017', periods=df_lenght, freq='H')

unique_jobs = ['job1','job2','job3',]
job_id = [unique_jobs for i in range (1, int((df_lenght/len(unique_jobs))+1) ,1) ]
df['job_id'] = sorted( [val for sublist in job_id for val in sublist] )

df.set_index(['job_id','datetime'], append=True, inplace=True)

print(df[:5]) 返回:

                                     a         b
  job_id datetime                               
0 job1   2017-06-23 00:00:00 -0.067011 -0.516382
1 job1   2017-06-23 01:00:00 -0.174199  0.068693
2 job1   2017-06-23 02:00:00 -1.227568 -0.103878
3 job1   2017-06-23 03:00:00 -0.847565 -0.345161
4 job1   2017-06-23 04:00:00  0.028852  3.111738

我需要重新采样 df['a'] 以得出每日滚动平均值,即应用 .resample('D').mean().rolling(window=2).mean()

我尝试了两种方法:

1 - 拆垛和堆叠,推荐here

df.unstack('job_id','datetime').resample('D').mean().rolling(window=2).mean().stack('job_id', 'datetime')

这会返回一个错误

2 - 使用pd.Grouper,推荐here

level_values = df.index.get_level_values
result = df.groupby( [ level_values(i) for i in [0,1] ] + [ pd.Grouper(freq='D', level=2) ] ).mean().rolling(window=2).mean()

这不会返回错误,但似乎没有对 df 进行适当的重新采样/分组。结果似乎包含每小时数据点,而不是每天:

print(result[:5])
                            a         b
  job_id datetime                      
0 job1   2017-06-23       NaN       NaN
1 job1   2017-06-23  0.831609  1.348970
2 job1   2017-06-23 -0.560047  1.063316
3 job1   2017-06-23 -0.641936 -0.199189
4 job1   2017-06-23  0.254402 -0.328190

【问题讨论】:

  • 你想如何处理job_id?
  • 在索引层次结构中,job_iddatetime 之前,即job_id 的每个值都会有一组datetime
  • Jobid 出现异常,重采样时如何处理?
  • @Allen 我已经修改了问题以更好地代表我的数据集

标签: python pandas grouping multi-index


【解决方案1】:

首先让我们定义一个重采样函数:

def resampler(x):    
    return x.set_index('datetime').resample('D').mean().rolling(window=2).mean()

然后,我们按 job_id 分组并应用重采样函数:

 df.reset_index(level=2).groupby(level=1).apply(resampler)

Out[657]: 
                          a         b
job_id datetime                      
job1   2017-06-23       NaN       NaN
       2017-06-24  0.053378  0.004727
       2017-06-25  0.265074  0.234081
       2017-06-26  0.192286  0.138148
job2   2017-06-26       NaN       NaN
       2017-06-27 -0.016629 -0.041284
       2017-06-28 -0.028662  0.055399
       2017-06-29  0.113299 -0.204670
job3   2017-06-29       NaN       NaN
       2017-06-30  0.233524 -0.194982
       2017-07-01  0.068839 -0.237573
       2017-07-02 -0.051211 -0.069917

让我知道这是否是你所追求的。

【讨论】:

  • 这似乎不适用于我的情况。我注意到您建议删除默认索引(带有数字),但是答案中的那一点消失了。这可能是阻止 groupby 工作的原因吗?
  • 我意识到我们可以忽略默认索引。当您运行代码时,它是否适用于您提供的示例数据?
【解决方案2】:

IIUC,您希望按job_id 和(每天)datetimes 分组,并希望忽略第一级 DataFrame 索引。因此,而不是分组

( [ level_values(i) for i in [0,1] ] + [ pd.Grouper(freq='D', level=2) ] )

你想分组

[df.index.get_level_values(1), pd.Grouper(freq='D', level=2)]

import numpy as np
import pandas as pd
np.random.seed(2017)

df_length = 240
df = pd.DataFrame(np.random.randn(df_length,2), columns=['a','b'] )
df['datetime'] = pd.date_range('23/06/2017', periods=df_length, freq='H')

unique_jobs = ['job1','job2','job3',]
job_id = [unique_jobs for i in range (1, int((df_length/len(unique_jobs))+1) ,1) ]
df['job_id'] = sorted( [val for sublist in job_id for val in sublist] )

df.set_index(['job_id','datetime'], append=True, inplace=True)

grouped = df.groupby([df.index.get_level_values(1), pd.Grouper(freq='D', level=2)])
result = grouped.mean().rolling(window=2).mean()

print(result)

产量

                          a         b
job_id datetime                      
job1   2017-06-23       NaN       NaN
       2017-06-24 -0.203083  0.176141
       2017-06-25 -0.077083  0.072510
       2017-06-26 -0.237611 -0.493329
job2   2017-06-26 -0.297775 -0.370543
       2017-06-27  0.005124  0.052603
       2017-06-28  0.226142 -0.015584
       2017-06-29 -0.065595  0.210628
job3   2017-06-29 -0.186865  0.347683
       2017-06-30  0.051508  0.029909
       2017-07-01  0.005341  0.075378
       2017-07-02 -0.027131  0.132192

【讨论】:

  • 非常感谢,您的解决方案也有效。我刚刚意识到使用多索引重新安排所有数据操作对我来说是多么棘手,因此我将尝试将slice 主 df 分成多个,即job_id 的每个值一个。不太确定如何做,可能使用字典?我将发布一个单独的问题
  • @Andreuccio:NumPy 和 Pandas 提供的向量化操作在应用于单个大数组或 NDFrame(而不是对较小数组或 NDFrame 进行多次调用)时表现最佳。因此,为了性能起见,通常最好保留一个带有 MultiIndex 的大 DataFrame,而不是一个包含较小 DataFrame 的 dict。如果性能是重中之重,您可能想提出一个关于如何处理 MultiIndex 的问题...
  • 我完全明白你的理由,但问题是我花了几天时间尝试使用多索引执行数据分析,所以我真的不担心多花几分钟的 CPU 时间!已在此处发布问题:stackoverflow.com/questions/44725105/…
  • 你能和我开个聊天室吗?
  • 对不起,这对我来说不是一个好时机,但如果您发表评论,我会尽力回复您。
猜你喜欢
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
  • 2018-09-28
  • 2019-03-05
  • 1970-01-01
相关资源
最近更新 更多