Pandas unstack但只为某些列创建多索引

时间:2014-05-06 09:20:39

标签: python-2.7 pandas

我有一个数据框,它是工厂的生产数据。工厂分为几个部分。数据的结构使得其中一列包含正确认为是标题的重复值。我需要重塑数据。所以在下面的DataFrame中,'质量'列包含4个度量,然后每小时测量一次。显然,这给了我们每行四个观测值。

这里的目标是转置这些数据,但是有些列是单索引而有些是多索引。行索引应保留['日期',' ID']。单个索引列应该是' line_no',' floor','买方'多指标列应该是每种质量指标的每小时量度。

我知道这是可能的,因为我不小心偶然发现了它。基本上,正如我的代码所示,我将所有内容都放在索引中,除了每小时数据,然后从索引中取消堆栈质量列。然后偶然,我试图重置索引,它创建了这个惊人的数据框架,其中一些列是单索引和一些多。当然,在索引中加载大量列是非常不切实际的,因为我们可能想要用它们做一些事情,比如改变它们。我的问题是如何实现这种类型的事情,而不必经历这个(我觉得是什么)的工作方式。

import random
import pandas as pd
d = {'ID'       : [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3] * 2,
     'Date'     : ['2013-05-04' for x in xrange(12)] + \
                  ['2013-05-06' for x in xrange(12)],
     'line_no'  : [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3] * 2,
     'floor'    : [5, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5] * 2,
     'buyer'    : ['buyer1', 'buyer1', 'buyer1', 'buyer1',\
                   'buyer2', 'buyer2', 'buyer2', 'buyer2',\
                   'buyer1', 'buyer1', 'buyer1', 'buyer1'] * 2,
     'Quality'  : ['no_checked', 'good', 'alter', 'rejected'] * 6,
     'Hour1'    : [random.randint(1000, 15000) for x in xrange(24)],
     'Hour2'    : [random.randint(1000, 15000) for x in xrange(24)],
     'Hour3'    : [random.randint(1000, 15000) for x in xrange(24)],
     'Hour4'    : [random.randint(1000, 15000) for x in xrange(24)],
     'Hour5'    : [random.randint(1000, 15000) for x in xrange(24)],
     'Hour6'    : [random.randint(1000, 15000) for x in xrange(24)]}
DF = pd.DataFrame(d, columns = ['ID', 'Date', 'line_no', 'floor', 'buyer',
                                'Quality', 'Hour1', 'Hour2', 'Hour3', 'Hour4',
                                'Hour5', 'Hour6'])
DF.set_index(['Date', 'ID'])

所以这就是我实现我想要的方式,但必须有一种方法可以做到这一点,而无需完成所有这些步骤。请帮忙......

# Reset the index
DF.reset_index(inplace = True)

# Put everything in the index
DF.set_index(['Date', 'ID', 'line_no', 'floor', 'buyer', 'Quality'], inplace = True)

# Unstack Quality
DFS = DF.unstack('Quality')

#Now this was the accidental workaround - gives exactly the result I want
DFS.reset_index(inplace = True)
DFS.set_index(['Date', 'ID'], inplace = True) 

所有帮助表示赞赏。很抱歉这个问题很长,但至少有一些数据可以使用!

1 个答案:

答案 0 :(得分:1)

一般来说inplace操作速度不快,恕我直言也不太可读。

In [18]: df.set_index(['Date','ID','Quality']).unstack('Quality'))
Out[18]: 
               line_no  floor   buyer  Hour1                               Hour2                               Hour3                               Hour4                               Hour5                               Hour6                             
Quality                                alter   good  no_checked  rejected  alter   good  no_checked  rejected  alter   good  no_checked  rejected  alter   good  no_checked  rejected  alter   good  no_checked  rejected  alter   good  no_checked  rejected
Date       ID                                                                                                                                                                                                                                                
2013-05-04 1         1      5  buyer1   6920   8681        9317     14631   5739   2112        4211     12026  13577   1855       13884     12710   7250   2540        1948      7116   9874   7302       10961      8251   3070   2793       14293     10895
           2         2      6  buyer2   7943   7501       13725      1648   7178   9670        6278      6888   9969  11766        9968      4722   7242   4049        6704      2225   6546   8688       11513     14550   2140  11941        1142      6683
           3         3      5  buyer1   5155   2449       13648      2183  14184   7309        1185     10454  11742  14102        2242     14297   6185   5554       12505     13312   3062   7426        4421      5693  12342  11622       10431     13375
2013-05-06 1         1      5  buyer1  14563   1343       14419      3350   8526   1185        5244     14777   2238   3640        6717      1109   7777  13136        1732      8681  14454   1059       10606      6942   9349   4524       13931     11799
           2         2      6  buyer2  14837   9524        8453      6074  11516  12356        9651     10650  15000  11374        4690     10914   1857   3231       14627      6590   6503   9268       13108      8581   8448  12013       14175     10783
           3         3      5  buyer1   9032  12959        4613      6793   7918   2827        6027     13002  11771  13370       12767     11080  12624  13269       11740     10543   8609  14709       11921     12484   8670  12706        8001      8991

[6 rows x 27 columns]

对于你正在做的事情是一个非常合理的习语