【问题标题】:Unpivot Pandas DataUnpivot Pandas 数据
【发布时间】:2013-08-18 00:27:30
【问题描述】:

我目前有一个DataFrame 布局为:

        Jan Feb Mar Apr ...
2001    1   12  12  19  
2002    9   ...
2003    ...

我想将数据“反透视”,使其看起来像:

Date    Value
Jan 2001    1
Feb 2001    1
Mar 2001    12
...
Jan 2002    9

使用 pandas/NumPy 完成此任务的最佳方法是什么?

【问题讨论】:

    标签: python pandas numpy dataframe


    【解决方案1】:

    您只需执行df.unstack(),这将创建一个MultiIndexed Series,其中月份为第一级,年份为第二级索引。如果您希望它们成为列,那么之后只需调用 reset_index()

    >>> df
          Jan  Feb
    2001    3    4
    2002    2    7
    >>> df.unstack()
    Jan  2001    3
         2002    2
    Feb  2001    4
         2002    7
    >>> df = df.unstack().reset_index(name='value')
    >>> df
      level_0  level_1  value
    0     Jan     2001      3
    1     Jan     2002      2
    2     Feb     2001      4
    3     Feb     2002      7
    >>> df.rename(columns={'level_0': 'month', 'level_1': 'year'}, inplace=True)
    >>> df
      month  year  value
    0   Jan  2001      3
    1   Jan  2002      2
    2   Feb  2001      4
    3   Feb  2002      7
    

    【讨论】:

      【解决方案2】:

      另一种解决方案是使用pandas.melt 来避免不必要地创建MultiIndex,尽管如果您的框架很小并且使用我的解决方案您仍然必须创建这不是那么昂贵“熔化”数据的临时文件。 melt 的胆量表明 id_varsvalue 都被复制,因为 id_vars 创建使用 tilevalue 创建使用 df.values.ravel('F') 我相信如果你的数据不是以 Fortran 顺序

      编辑:我不确定何时会在调用 ravel 时创建副本,因为 order 参数仅指示您希望数据的读取方式读取并且文档字符串说仅在需要时才制作副本。

      In [99]: mons
      Out[99]:
      ['Jan',
       'Feb',
       'Mar',
       'Apr',
       'May',
       'Jun',
       'Jul',
       'Aug',
       'Sep',
       'Oct',
       'Nov',
       'Dec']
      
      In [100]: df = DataFrame(randn(201, len(mons)), columns=mons, index=map(str, arange(1901, 2102)))
      
      In [101]: df.head()
      Out[101]:
              Jan    Feb    Mar    Apr    May    Jun    Jul    Aug    Sep    Oct  \
      1901  1.141 -0.270  0.329  0.214 -1.030  0.324 -1.448  2.003 -0.061  0.477
      1902  0.136  0.151  0.447 -0.493  1.329  1.410  0.020 -0.705  0.870  0.478
      1903 -0.000  0.689  1.768 -0.057 -1.471  0.515 -0.315  0.703  2.511  0.592
      1904  1.199  1.246 -0.255  0.182 -0.454 -0.452  1.074  0.178  2.495 -0.543
      1905  1.073  1.375 -1.837  1.048 -0.139 -0.273 -0.958 -1.164 -1.012  0.950
      
              Nov    Dec
      1901  0.102  0.122
      1902  2.941  0.654
      1903  0.347 -1.636
      1904 -0.047  0.457
      1905  1.277 -0.284
      
      In [102]: df.reset_index(inplace=True)
      
      In [103]: df.head()
      Out[103]:
        index    Jan    Feb    Mar    Apr    May    Jun    Jul    Aug    Sep    Oct  \
      0  1901  1.141 -0.270  0.329  0.214 -1.030  0.324 -1.448  2.003 -0.061  0.477
      1  1902  0.136  0.151  0.447 -0.493  1.329  1.410  0.020 -0.705  0.870  0.478
      2  1903 -0.000  0.689  1.768 -0.057 -1.471  0.515 -0.315  0.703  2.511  0.592
      3  1904  1.199  1.246 -0.255  0.182 -0.454 -0.452  1.074  0.178  2.495 -0.543
      4  1905  1.073  1.375 -1.837  1.048 -0.139 -0.273 -0.958 -1.164 -1.012  0.950
      
           Nov    Dec
      0  0.102  0.122
      1  2.941  0.654
      2  0.347 -1.636
      3 -0.047  0.457
      4  1.277 -0.284
      
      In [104]: res = pd.melt(df, id_vars=['index'], var_name=['months'])
      
      In [105]: res['date'] = res['months'] + ' ' + res['index']
      
      In [106]: res.head()
      Out[106]:
        index months  value      date
      0  1901    Jan  1.141  Jan 1901
      1  1902    Jan  0.136  Jan 1902
      2  1903    Jan -0.000  Jan 1903
      3  1904    Jan  1.199  Jan 1904
      4  1905    Jan  1.073  Jan 1905
      

      【讨论】:

        【解决方案3】:

        df.reset_index().melt(...) 应该取消它(credit):

        >>> df = pd.DataFrame({
        ...     'foo': ['one', 'one', 'one', 'two', 'two', 'two'],
        ...     'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
        ...     'baz': [1, 2, 3, 4, 5, 6],
        ... })
        >>> df
           foo bar  baz
        0  one   A    1
        1  one   B    2
        2  one   C    3
        3  two   A    4
        4  two   B    5
        5  two   C    6
        
        >>> df_piv = df.pivot(index='foo', columns='bar', values='baz')
        >>> df_piv
        bar  A   B   C
        foo
        one  1   2   3
        two  4   5   6
        
        >>> def_piv_unpiv = df_piv.reset_index().melt(id_vars='foo', var_name='bar', value_name='baz')
        >>> def_piv_unpiv
           foo bar  baz
        0  one   A    1
        1  two   A    4
        2  one   B    2
        3  two   B    5
        4  one   C    3
        5  two   C    6
        

        编辑:后来我意识到这基本上是Phillip Cloud's answer 的更简洁版本。

        【讨论】:

          猜你喜欢
          • 2016-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-12
          • 1970-01-01
          • 1970-01-01
          • 2021-10-03
          • 1970-01-01
          相关资源
          最近更新 更多