如何在Pandas上切片Multiindex时间序列数据帧?

时间:2014-06-04 10:11:46

标签: python pandas

我必须切片由此代码

创建的数据框
data = pd.read_csv(("/user_home/w_hugopires/dados/dados_meteo.csv"),names=['POM','DTM','RNF','WET','HMD','TMP','DEW','INF'])
data['DTM'] = pd.to_datetime(data['DTM'], coerce = True)
data.set_index(['POM', 'DTM'], inplace=True)

首先,我必须创建一个Multindex,因为在几个POM(自动气象站)之间重复有DTM(时间戳)。

结果是

                                RNF WET HMD TMP DEW INF
POM         DTM                     
QuintaVilar 2011-11-01 00:00:00  0   0   0   0   0   0
            2011-11-01 00:15:00  0   0   0   0   0   0
            2011-11-01 00:30:00  0   0   0   0   0   0
            2011-11-01 00:45:00  0   0   0   0   0   0
            2011-11-01 01:00:00  0   0   0   0   0   0

然后我使用以下代码创建数据帧的切片

intervalo = data[['TMP','RNF']].ix[pom1][start_year + start_month + start_day : final_year + final_month + final_day]

结果是

    TMP RNF
DTM     
2013-04-01 00:12:00  12.5    0
2013-04-01 00:27:00  12.1    0
2013-04-01 00:42:00  12.1    0
2013-04-01 00:57:00  11.7    0
2013-04-01 01:12:00  11.7    0

如何切割多个POM以及如何切割多个时间间隔(例如每年的每年四月)?

谢谢

雨果

1 个答案:

答案 0 :(得分:4)

示例数据框:

In [4]: data = pd.DataFrame(np.zeros((15,3)), columns=['RNF', 'WET', 'HMD'])            
   ...: data['DTM'] = pd.date_range('2012-01-01', periods=5, freq='D').tolist()*3
   ...: data['POM'] = ['station1']*5 + ['station2']*5 + ['station3']*5
   ...: data = data.set_index(['POM', 'DTM'])


In [5]: data
Out[5]: 
                     RNF  WET  HMD
POM      DTM                      
station1 2012-01-01    0    0    0
         2012-01-02    0    0    0
         2012-01-03    0    0    0
         2012-01-04    0    0    0
         2012-01-05    0    0    0
station2 2012-01-01    0    0    0
         2012-01-02    0    0    0
         2012-01-03    0    0    0
         2012-01-04    0    0    0
         2012-01-05    0    0    0
station3 2012-01-01    0    0    0
         2012-01-02    0    0    0
         2012-01-03    0    0    0
         2012-01-04    0    0    0
         2012-01-05    0    0    0

<强> 1。如何切割多个POM?

要只切片第一级,你可以提供一个列表(例如data.loc[['station1', 'station2']])或只是切片(例如data.loc['station1':'station3']),但我想你的意思是如何在这样的时候切片第二级在第一级选择多个元素?

使用版本0.14中的新多索引功能(请参阅whatsnew docs),您只需切换第二级即可轻松完成此操作:

In [8]: idx = pd.IndexSlice

In [9]: data.loc[idx[['station1', 'station2'], '2012-01-02':'2012-01-04'], :]
Out[9]: 
                     RNF  WET  HMD
POM      DTM                      
station1 2012-01-02    0    0    0
         2012-01-03    0    0    0
         2012-01-04    0    0    0
station2 2012-01-02    0    0    0
         2012-01-03    0    0    0
         2012-01-04    0    0    0

这相当于

data.loc[(['station1', 'station2'], slice('2012-01-02','2012-01-04')), :]

但提供pd.IndexSlice是为了不需要执行slice(...)

如果您没有pandas版本0.14 ,另一种方法是将数据帧取消堆叠(将'station'索引级别转移到列):

In [12]: data2 = data.unstack(level=0).reorder_levels([1,0], axis=1).sort_index(axis=1)

In [13]: data2
Out[13]: 
POM         station1        station2        station3          
            RNF  WET  HMD   RNF  WET  HMD   RNF  WET  HMD
DTM                                                              
2012-01-01  0    0    0     0    0    0     0    0    0
2012-01-02  0    0    0     0    0    0     0    0    0
2012-01-03  0    0    0     0    0    0     0    0    0
2012-01-04  0    0    0     0    0    0     0    0    0
2012-01-05  0    0    0     0    0    0     0    0    0

然后您可以轻松切片行:

data2['2012-01-02':'2012-01-04']

如果您希望将其恢复为原始格式,则必须stack返回(由于reorder_levels在现有行索引之后插入'station',因此需要stack,虽然我们希望它作为行索引的第一级):

data2['2012-01-02':'2012-01-04'].stack(0).reorder_levels([1,0], axis=0).sort_index(axis=0)

<强> 2。如何切割多个时间间隔(例如每年的每年四月)?

您可以使用布尔索引来执行此操作。举个例子来得到第2天和第4天:

In [22]: time_index = data.index.get_level_values(1)

In [23]: selection = (time_index.day == 2) | (time_index.day == 4)

In [24]: data[selection]
Out[24]: 
                     RNF  WET  HMD
POM      DTM                      
station1 2012-01-02    0    0    0
         2012-01-04    0    0    0
station2 2012-01-02    0    0    0
         2012-01-04    0    0    0
station3 2012-01-02    0    0    0
         2012-01-04    0    0    0

在你的情况下(例如每年4月份),这将是data[time_index.month == 4]

在这种情况下,将它与第一级(站点)的多个选择结合起来会更困难,但是你可以在这个布尔索引之后执行此操作),或者你可以在'unstacked'数据帧上执行此操作(请参阅以上示例data2)。


您可能想要考虑的其他事项。根据您的应用程序,我个人认为在列索引中存储不同的站而不是行(因此具有列多索引)可能更方便,如data2所示。