zoukankan      html  css  js  c++  java
  • 10.29

    pandas将“长格式”旋转为“宽格式”

    多个时间序列数据通常是以所谓的“长格式”(long)或“堆叠格式”(stacked)存储在数据库和CSV中的。我们先加载一些示例数据,做一些时间序列规整和数据清洗:

    In [139]: data = pd.read_csv('examples/macrodata.csv')
    
    In [140]: data.head()
    Out[140]: 
         year  quarter   realgdp  realcons  realinv  realgovt  realdpi    cpi  
    0  1959.0      1.0  2710.349    1707.4  286.898   470.045   1886.9  28.98   
    1  1959.0      2.0  2778.801    1733.7  310.859   481.301   1919.7  29.15   
    2  1959.0      3.0  2775.488    1751.8  289.226   491.260   1916.4  29.35   
    3  1959.0      4.0  2785.204    1753.7  299.356   484.052   1931.3  29.37   
    4  1960.0      1.0  2847.699    1770.5  331.722   462.199   1955.5  29.54   
          m1  tbilrate  unemp      pop  infl  realint  
    0  139.7      2.82    5.8  177.146  0.00     0.00
    1  141.7      3.08    5.1  177.830  2.34     0.74  
    2  140.5      3.82    5.3  178.657  2.74     1.09  
    3  140.0      4.33    5.6  179.386  0.27     4.06  
    4  139.6      3.50    5.2  180.007  2.31     1.19  
    
    In [141]: periods = pd.PeriodIndex(year=data.year, quarter=data.quarter,
       .....:                          name='date')
    
    In [142]: columns = pd.Index(['realgdp', 'infl', 'unemp'], name='item')
    
    In [143]: data = data.reindex(columns=columns)
    
    In [144]: data.index = periods.to_timestamp('D', 'end')
    
    In [145]: ldata = data.stack().reset_index().rename(columns={0: 'value'})

    这就是多个时间序列(或者其它带有两个或多个键的可观察数据,这里,我们的键是date和item)的长格式。表中的每行代表一次观察。

    关系型数据库(如MySQL)中的数据经常都是这样存储的,因为固定架构(即列名和数据类型)有一个好处:随着表中数据的添加,item列中的值的种类能够增加。在前面的例子中,date和item通常就是主键(用关系型数据库的说法),不仅提供了关系完整性,而且提供了更为简单的查询支持。有的情况下,使用这样的数据会很麻烦,你可能会更喜欢DataFrame,不同的item值分别形成一列,date列中的时间戳则用作索引。DataFrame的pivot方法完全可以实现这个转换:

    In [147]: pivoted = ldata.pivot('date', 'item', 'value')
    
    In [148]: pivoted
    Out[148]: 
    item        infl    realgdp  unemp
    date                              
    1959-03-31  0.00   2710.349    5.8
    1959-06-30  2.34   2778.801    5.1
    1959-09-30  2.74   2775.488    5.3
    1959-12-31  0.27   2785.204    5.6
    1960-03-31  2.31   2847.699    5.2
    1960-06-30  0.14   2834.390    5.2
    1960-09-30  2.70   2839.022    5.6
    1960-12-31  1.21   2802.616    6.3
    1961-03-31 -0.40   2819.264    6.8
    1961-06-30  1.47   2872.005    7.0
    ...          ...        ...    ...
    2007-06-30  2.75  13203.977    4.5
    2007-09-30  3.45  13321.109    4.7
    2007-12-31  6.38  13391.249    4.8
    2008-03-31  2.82  13366.865    4.9
    2008-06-30  8.53  13415.266    5.4
    2008-09-30 -3.16  13324.600    6.0
    2008-12-31 -8.79  13141.920    6.9
    2009-03-31  0.94  12925.410    8.1
    2009-06-30  3.37  12901.504    9.2
    2009-09-30  3.56  12990.341    9.6
    [203 rows x 3 columns]

    前两个传递的值分别用作行和列索引,最后一个可选值则是用于填充DataFrame的数据列。假设有两个需要同时重塑的数据列:

    In [149]: ldata['value2'] = np.random.randn(len(ldata))
    
    In [150]: ldata[:10]
    Out[150]: 
            date     item     value    value2
    0 1959-03-31  realgdp  2710.349  0.523772
    1 1959-03-31     infl     0.000  0.000940
    2 1959-03-31    unemp     5.800  1.343810
    3 1959-06-30  realgdp  2778.801 -0.713544
    4 1959-06-30     infl     2.340 -0.831154
    5 1959-06-30    unemp     5.100 -2.370232
    6 1959-09-30  realgdp  2775.488 -1.860761
    7 1959-09-30     infl     2.740 -0.860757
    8 1959-09-30    unemp     5.300  0.560145
    9 1959-12-31  realgdp  2785.204 -1.265934

    如果忽略最后一个参数,得到的DataFrame就会带有层次化的列:

    In [151]: pivoted = ldata.pivot('date', 'item')
    
    In [152]: pivoted[:5]
    Out[152]: 
               value                    value2                    
    item        infl   realgdp unemp      infl   realgdp     unemp
    date                                                          
    1959-03-31  0.00  2710.349   5.8  0.000940  0.523772  1.343810
    1959-06-30  2.34  2778.801   5.1 -0.831154 -0.713544 -2.370232
    1959-09-30  2.74  2775.488   5.3 -0.860757 -1.860761  0.560145
    1959-12-31  0.27  2785.204   5.6  0.119827 -1.265934 -1.063512
    1960-03-31  2.31  2847.699   5.2 -2.359419  0.332883 -0.199543
    
    In [153]: pivoted['value'][:5]
    Out[153]: 
    item        infl   realgdp  unemp
    date                             
    1959-03-31  0.00  2710.349    5.8
    1959-06-30  2.34  2778.801    5.1
    1959-09-30  2.74  2775.488    5.3
    1959-12-31  0.27  2785.204    5.6
    1960-03-31  2.31  2847.699    5.2

    注意,pivot其实就是用set_index创建层次化索引,再用unstack重塑:

    In [154]: unstacked = ldata.set_index(['date', 'item']).unstack('item')
    
    In [155]: unstacked[:7]
    Out[155]: 
               value                    value2                    
    item        infl   realgdp unemp      infl   realgdp     unemp
    date                                                          
    1959-03-31  0.00  2710.349   5.8  0.000940  0.523772  1.343810
    1959-06-30  2.34  2778.801   5.1 -0.831154 -0.713544 -2.370232
    1959-09-30  2.74  2775.488   5.3 -0.860757 -1.860761  0.560145
    1959-12-31  0.27  2785.204   5.6  0.119827 -1.265934 -1.063512
    1960-03-31  2.31  2847.699   5.2 -2.359419  0.332883 -0.199543
    1960-06-30  0.14  2834.390   5.2 -0.970736 -1.541996 -1.307030
    1960-09-30  2.70  2839.022   5.6  0.377984  0.286350 -0.753887
  • 相关阅读:
    Thrift在微服务中的使用
    MySQL 必知必会
    IDEA 内使用 git
    分布式锁
    LeetCode 图
    LeetCode 位运算
    LeetCode 数组
    LeetCode 字符串
    LeetCode 哈希表
    LeetCode 栈和队列
  • 原文地址:https://www.cnblogs.com/zhaoyids/p/14867146.html
Copyright © 2011-2022 走看看