如何在pandas数据帧中组织结构化数据

时间:2012-09-22 13:54:10

标签: python pandas pivot-table

假设我有一个DataFrame,它具有如下所示的子索引结构,带有'date','tenor''mat'和'strike',并且要观察的字段存储在'vol'列中:

date     tenor   mat strike    vol                                      
20120903 3m      1y  0.25      52.
                     0.50      51.
                     1.00      49.
20120903 3m      5y  0.25      32.
                     0.50      55.
                     1.00      23.
20120903 3m      10y 0.25      65.
                     0.50      55.
                     1.00      19.
20120904 3m      1y  0.25      32.
                     0.50      57.
                     1.00      44.
20120904 3m      5y  0.25      54.
                     0.50      50.
                     1.00      69.
20120904 3m      10y 0.25      42.
                     0.50      81.
                     1.00      99.

假设我想通过获取带有子索引'date'+'tenor'的新数据帧以及由'mat','strike'和'vol'组成的3d数组给出的'values'来重新组织这些数据数据帧的方式如下:

date     tenor   values                                                       
20120903 3m      [[1y,5y,10y],[0.25, 0.50, 1.00], [52., 51., 49.],
                                                  [32., 55., 23.],
                                                  [65., 55., 19.]]
20120904 3m      [[1y,5y,10y],[0.25, 0.50, 1.00], [32., 57., 44.],
                                                  [54., 50., 69.],
                                                  [42., 81., 99.]]

我尝试了'unstack','groupby'和'pivot'的各种尝试但没有成功。我只能通过使用大量的python向量操作来实现我的目标,但这是一个缓慢而低效的过程。是否有任何特定的,更有效的熊猫程序,以获得相同的结果?我迷路了...... 谢谢你的帮助, 莫里吉奥

1 个答案:

答案 0 :(得分:3)

这样的事情怎么样:

In [111]: df
Out[111]: 
                mat  strike  vol
date     tenor                  
20120903 3m      1y    0.25   52
         3m      1y    0.50   51
         3m      1y    1.00   49
         3m      5y    0.25   32
         3m      5y    0.50   55
         3m      5y    1.00   23
         3m     10y    0.25   65
         3m     10y    0.50   55
         3m     10y    1.00   19
20120904 3m      1y    0.25   32
         3m      1y    0.50   57
         3m      1y    1.00   44
         3m      5y    0.25   54
         3m      5y    0.50   50
         3m      5y    1.00   69
         3m     10y    0.25   42
         3m     10y    0.50   81
         3m     10y    1.00   99

In [112]: def agg_func(x):
    mats = list(x.mat.unique())
    strikes = list(x.strike.unique())
    vols = x.pivot('mat', 'strike', 'vol').reindex(mats, columns=strikes)
    return [mats, strikes, vols.values.tolist()]
   .....: 

In [113]: rs = df.groupby(level=['date', 'tenor']).apply(agg_func)

In [114]: rs
Out[114]: 
date      tenor
20120903  3m       [['1y', '5y', '10y'], [0.25, 0.5, 1.0], [[52.0...
20120904  3m       [['1y', '5y', '10y'], [0.25, 0.5, 1.0], [[32.0...

In [115]: rs.values[0]
Out[115]: 
[['1y', '5y', '10y'],
 [0.25, 0.5, 1.0],
 [[52.0, 51.0, 49.0], [32.0, 55.0, 23.0], [65.0, 55.0, 19.0]]]