展平pandas DataFrame,不使用数据透视表

时间:2017-07-20 18:45:12

标签: python pandas pivot

我在调用groupby后有一个MultiIndex pandas DataFrame,需要以时尚similar to flattening a pivot table展平它。大多数分析都是围绕分组对象构建的,因此不希望重构为数据透视表。

考虑一些虚拟数据,

dummy_data = pd.DataFrame({'Ccy' : ['EUR', 'EUR', 'CAD', 'CAD', 'EUR', 'EUR', 'CAD', 'EUR'],
                  'Venue' : ['BAML']*5 + ['BARX']*3,
                  'Price': np.abs(np.random.randn(8)),
                  'volume': np.abs(10*np.random.randn(8))
                   }, 
                  index = pd.date_range('7/19/2017', periods=8))

dummy_data.index.name = "datetime"
print dummy_data


>>>            Ccy     Price Venue     volume
datetime                                  
2017-07-19  EUR  1.338521  BAML  11.227553
2017-07-20  EUR  0.882715  BAML   0.307711
2017-07-21  CAD  0.977815  BAML  14.196170
2017-07-22  CAD  1.262272  BAML   0.055213
2017-07-23  EUR  0.752433  BAML   5.315777
2017-07-24  EUR  0.699008  BARX   2.299045
2017-07-25  CAD  1.625567  BARX   6.474822
2017-07-26  EUR  2.122562  BARX   5.026135

目标是按CcyVenue对数据进行分组,对每个子组应用filter操作,然后将这些组展平回原始帧的格式。考虑一个保留price > 0.8

行的简单过滤器
dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8])

>>>                      Ccy     Price Venue     volume
Ccy Venue datetime                                  
CAD BAML  2017-07-21  CAD  0.977815  BAML  14.196170
          2017-07-22  CAD  1.262272  BAML   0.055213
    BARX  2017-07-25  CAD  1.625567  BARX   6.474822
EUR BAML  2017-07-19  EUR  1.338521  BAML  11.227553
          2017-07-20  EUR  0.882715  BAML   0.307711
    BARX  2017-07-26  EUR  2.122562  BARX   5.026135

我现在需要的是填写/展平CcyVenue列,以便

Ccy Venue datetime                                  
CAD BAML  2017-07-21  ...                       CAD BAML 2017-07-21  ...
          2017-07-22  ...                       CAD BAML 2017-07-22  ... 
    BARX  2017-07-25  ...    ---> BECOMES --->  CAD BARX 2017-07-25 ...
EUR BAML  2017-07-19  ...                       EUR BAML 2017-07-19 ... 
          2017-07-20  ...                       EUR BAML 2017-07-20  ...

我需要这样做,因为我们有一系列绘图实用程序,它们不够灵活,无法处理分组数据。不应该有ungroup()flatten()方法与groupby()操作相互作用吗?

注意:此示例中的普通过滤器可能已应用于未分组数据。实际上,我的过滤器更复杂,只对子组有意义。

解决方案尝试(尝试pivot table solution中的1和2)

尝试1 melt方法丢失datetime索引。

    print dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8]).melt()

>>>   variable      value
0       Ccy        CAD
1       Ccy        CAD
2       Ccy        CAD
3       Ccy        EUR
4       Ccy        EUR
5       Ccy        EUR
6     Price   0.977815
7     Price    1.26227
8     Price    1.62557
9     Price    1.33852

尝试2: accepted answer导致KeyError

dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8]).unstack().reset_index().drop('level_0', axis=1)
  

KeyError:'level_0'

尝试3: reset_index()导致ValueError

dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8]).reset_index()
  

ValueError:无法插入Venue,已存在

尝试4: as_index=False(不含group_keys个关键字)

out = dummy_data.groupby(['Ccy', 'Venue'], as_index=False).apply(lambda x: x[x['Price'] > 0.8])
print out
print out.index

              Ccy     Price Venue     volume
  datetime                                  
0 2017-07-21  CAD  0.977815  BAML  14.196170
  2017-07-22  CAD  1.262272  BAML   0.055213
1 2017-07-25  CAD  1.625567  BARX   6.474822
2 2017-07-19  EUR  1.338521  BAML  11.227553
  2017-07-20  EUR  0.882715  BAML   0.307711
3 2017-07-26  EUR  2.122562  BARX   5.026135
MultiIndex(levels=[[0, 1, 2, 3], [2017-07-19 00:00:00, 2017-07-20 00:00:00, 2017-07-21 00:00:00, 2017-07-22 00:00:00, 2017-07-25 00:00:00, 2017-07-26 00:00:00]],
           labels=[[0, 0, 1, 2, 2, 3], [2, 3, 4, 0, 1, 5]],
           names=[None, u'datetime'])

这让我非常接近,但这个对象仍然是MultiIndexed。我们怎样才能获得日期时间索引?

1 个答案:

答案 0 :(得分:2)

这可能是你想要的:

dummy_data.groupby(['Ccy', 'Venue'], group_keys=False)\
          .apply(lambda x: x[x['Price'] > 0.8])