pandas教程:Reshaping and Pivoting 整形和旋转

文章目录

  • 8.3 Reshaping and Pivoting(整形和旋转)
  • 1 Reshaping with Hierarchical Indexing(对多层级索引进行整形)
  • 2 Pivoting “Long” to “Wide” Format(把“长”格式旋转为“宽”格式)
  • 3 Pivoting “Wide” to “Long” Format(把“宽”格式旋转为“长”格式)

8.3 Reshaping and Pivoting(整形和旋转)

有很多用于整理表格型数据的基本操作,指的就是reshapepivot

1 Reshaping with Hierarchical Indexing(对多层级索引进行整形)

多层级索引提供一套统一的方法来整理DataFrame中数据。主要有两个操作:

stack
  • 这个操作会把列旋转为行
unstack
  • 这个会把行变为列

下面我们会给出一些例子。这里有一个DataFrame,我们用字符串数组来作为行和列的索引:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(6).reshape((2, 3)),
                    index=pd.Index(['Ohio', 'Colorado'], name='state'), 
                    columns=pd.Index(['one', 'two', 'three'], 
                    name='number'))
data
number one two three
state
Ohio 0 1 2
Colorado 3 4 5

使用stack方法会把列数据变为行数据,产生一个Series

result = data.stack()
result
state     number
Ohio      one       0
          two       1
          three     2
Colorado  one       3
          two       4
          three     5
dtype: int64

对于一个有多层级索引的Series,可以用unstack把它变回DataFrame

result.unstack()
number one two three
state
Ohio 0 1 2
Colorado 3 4 5

默认会把最内层的层级unstack(取消堆叠),stack默认也是这样。我们可以传入一个表示层级的数字或名字,来指定取消堆叠某个层级:

result.unstack(0)
state Ohio Colorado
number
one 0 3
two 1 4
three 2 5
result.unstack('state')
state Ohio Colorado
number
one 0 3
two 1 4
three 2 5

如果某个层级里的值不能在subgroup(子组)里找到的话,unstack可能会引入缺失值:

s1 = pd.Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd'])

s2 = pd.Series([4, 5, 6], index=['c', 'd', 'e'])

data2 = pd.concat([s1, s2], keys=['one', 'two'])
data2
one  a    0
     b    1
     c    2
     d    3
two  c    4
     d    5
     e    6
dtype: int64
data2.unstack()
a b c d e
one 0.0 1.0 2.0 3.0 NaN
two NaN NaN 4.0 5.0 6.0

stack默认会把缺失值过滤掉,所以这两种操作是可逆的:

data2.unstack()
a b c d e
one 0.0 1.0 2.0 3.0 NaN
two NaN NaN 4.0 5.0 6.0
data2.unstack().stack()
one  a    0.0
     b    1.0
     c    2.0
     d    3.0
two  c    4.0
     d    5.0
     e    6.0
dtype: float64
data2.unstack().stack(dropna=False)
one  a    0.0
     b    1.0
     c    2.0
     d    3.0
     e    NaN
two  a    NaN
     b    NaN
     c    4.0
     d    5.0
     e    6.0
dtype: float64

如果对一个DataFrame使用unstack,被取消堆叠(unstack)的层级会变为结果中最低的层级:

df = pd.DataFrame({'left': result, 'right': result + 5}, 
                  columns=pd.Index(['left', 'right'], name='side'))
df # 行的话,有state和number两个层级,number是内层级。而列的话有side这一个层级
side left right
state number
Ohio one 0 5
two 1 6
three 2 7
Colorado one 3 8
two 4 9
three 5 10
df.unstack('state')  # state被unstack后,变为比side更低的层级
side left right
state Ohio Colorado Ohio Colorado
number
one 0 3 5 8
two 1 4 6 9
three 2 5 7 10

调用stack的时候,可以指明想要stack(堆叠)哪一个轴:

df.unstack('state').stack('side')
state Ohio Colorado
number side
one left 0 3
right 5 8
two left 1 4
right 6 9
three left 2 5
right 7 10

2 Pivoting “Long” to “Wide” Format(把“长”格式旋转为“宽”格式)

一种用来把多重时间序列数据存储在数据库和CSV中的格式叫long or stacked format(长格式或堆叠格式)。下面我们加载一些数据,处理一下时间序列文件并做一些数据清理工作:

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

对于PeriodIndex,我们会在第十一章讲得更详细些。在这里,这个函数把yearquarter这两列整合起来作为一种时间间隔类型。

ldata看起来是这样的:

ldata[:10]
date item value
0 1959-03-31 realgdp 2710.349
1 1959-03-31 infl 0.000
2 1959-03-31 unemp 5.800
3 1959-06-30 realgdp 2778.801
4 1959-06-30 infl 2.340
5 1959-06-30 unemp 5.100
6 1959-09-30 realgdp 2775.488
7 1959-09-30 infl 2.740
8 1959-09-30 unemp 5.300
9 1959-12-31 realgdp 2785.204

这种格式叫做long format for multiple time series(用于多重时间序列的长格式),或者有两个以上键(keys)的观测数据(在这个例子里,keys指的是dateitem)。表格中的每一行表示一个观测数据。

这种数据经常被存储于关系型数据库中,比如MySQL,这种固定的模式(列名和数据类型)能让作为item列中不同的数据,添加到表格中。在前一个例子里,dateitem通常被用来当做primary keys(主键,这是关系型数据库里的术语),能实现relational integrity(关系完整性)和更方便的join(联结)。但是在一些例子里,这种格式的数据并不好处理;我们可能更喜欢有一个DataFrame,其中一列能有不同的item值,并用date列作为索引。DataFrame中的pivot方法,就能做到这种转换:

pivoted = ldata.pivot('date', 'item', 'value')
pivoted
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
1961-09-30 0.80 2918.419 6.8
1961-12-31 0.80 2977.830 6.2
1962-03-31 2.26 3031.241 5.6
1962-06-30 0.13 3064.709 5.5
1962-09-30 2.11 3093.047 5.6
1962-12-31 0.79 3100.563 5.5
1963-03-31 0.53 3141.087 5.8
1963-06-30 2.75 3180.447 5.7
1963-09-30 0.78 3240.332 5.5
1963-12-31 2.46 3264.967 5.6
1964-03-31 0.13 3338.246 5.5
1964-06-30 0.90 3376.587 5.2
1964-09-30 1.29 3422.469 5.0
1964-12-31 2.05 3431.957 5.0
1965-03-31 1.28 3516.251 4.9
1965-06-30 2.54 3563.960 4.7
1965-09-30 0.89 3636.285 4.4
1965-12-31 2.90 3724.014 4.1
1966-03-31 4.99 3815.423 3.9
1966-06-30 2.10 3828.124 3.8
... ... ... ...
2002-06-30 1.56 11538.770 5.8
2002-09-30 2.66 11596.430 5.7
2002-12-31 3.08 11598.824 5.8
2003-03-31 1.31 11645.819 5.9
2003-06-30 1.09 11738.706 6.2
2003-09-30 2.60 11935.461 6.1
2003-12-31 3.02 12042.817 5.8
2004-03-31 2.35 12127.623 5.7
2004-06-30 3.61 12213.818 5.6
2004-09-30 3.58 12303.533 5.4
2004-12-31 2.09 12410.282 5.4
2005-03-31 4.15 12534.113 5.3
2005-06-30 1.85 12587.535 5.1
2005-09-30 9.14 12683.153 5.0
2005-12-31 0.40 12748.699 4.9
2006-03-31 2.60 12915.938 4.7
2006-06-30 3.97 12962.462 4.7
2006-09-30 -1.58 12965.916 4.7
2006-12-31 3.30 13060.679 4.4
2007-03-31 4.58 13099.901 4.5
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 × 3 columns

前两个传入的值是列,分别被用于作为行索引和列索引(date是行索引,item是列索引),最后是一个是可选的value column(值列),用于填充DataFrame。假设我们有两列值,我们想要同时整形:

ldata['value2'] = np.random.randn(len(ldata))
ldata[:10]
date item value value2
0 1959-03-31 realgdp 2710.349 0.284176
1 1959-03-31 infl 0.000 -1.428019
2 1959-03-31 unemp 5.800 -1.238330
3 1959-06-30 realgdp 2778.801 0.144937
4 1959-06-30 infl 2.340 -0.553085
5 1959-06-30 unemp 5.100 -0.833374
6 1959-09-30 realgdp 2775.488 0.147826
7 1959-09-30 infl 2.740 -0.059040
8 1959-09-30 unemp 5.300 0.531887
9 1959-12-31 realgdp 2785.204 -0.169839

舍弃最后一个参数,我们能得到一个有多层级列的DataFrame

pivoted = ldata.pivot('date', 'item')
pivoted[:5]
value value2
item infl realgdp unemp infl realgdp unemp
date
1959-03-31 0.00 2710.349 5.8 -1.428019 0.284176 -1.238330
1959-06-30 2.34 2778.801 5.1 -0.553085 0.144937 -0.833374
1959-09-30 2.74 2775.488 5.3 -0.059040 0.147826 0.531887
1959-12-31 0.27 2785.204 5.6 -0.436330 -0.169839 -0.203380
1960-03-31 2.31 2847.699 5.2 1.038559 0.644242 -1.872500
pivoted['value'][:5]
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

unstacked = ldata.set_index(['date', 'item']).unstack('item')
unstacked[:7]
value value2
item infl realgdp unemp infl realgdp unemp
date
1959-03-31 0.00 2710.349 5.8 -1.428019 0.284176 -1.238330
1959-06-30 2.34 2778.801 5.1 -0.553085 0.144937 -0.833374
1959-09-30 2.74 2775.488 5.3 -0.059040 0.147826 0.531887
1959-12-31 0.27 2785.204 5.6 -0.436330 -0.169839 -0.203380
1960-03-31 2.31 2847.699 5.2 1.038559 0.644242 -1.872500
1960-06-30 0.14 2834.390 5.2 0.765028 -0.835805 2.014334
1960-09-30 2.70 2839.022 5.6 0.168310 0.362230 1.603777

3 Pivoting “Wide” to “Long” Format(把“宽”格式旋转为“长”格式)

用于DataFrame,与pivot相反的操作是pandas.melt。相对于把一列变为多列的pivotmelt会把多列变为一列,产生一个比输入的DataFrame还要长的结果。看一下例子:

df = pd.DataFrame({'key': ['foo', 'bar', 'baz'], 
                   'A': [1, 2, 3], 
                   'B': [4, 5, 6], 
                   'C': [7, 8, 9]})
df
A B C key
0 1 4 7 foo
1 2 5 8 bar
2 3 6 9 baz

'key’列可以作为group indicator(群指示器),其他列可以作为数据值。当使用pandas.melt,我们必须指明哪些列是群指示器。这里我们令key作为群指示器:

melted = pd.melt(df, ['key'])
melted
key variable value
0 foo A 1
1 bar A 2
2 baz A 3
3 foo B 4
4 bar B 5
5 baz B 6
6 foo C 7
7 bar C 8
8 baz C 9

使用pivot,我们可以得到原来的布局:

reshaped = melted.pivot('key', 'variable', 'value')
reshaped
variable A B C
key
bar 2 5 8
baz 3 6 9
foo 1 4 7

因为pivot会给行标签创建一个索引(key列),所以这里我们要用reset_index来让数据变回去:

reshaped.reset_index()
variable key A B C
0 bar 2 5 8
1 baz 3 6 9
2 foo 1 4 7

当然,我们也可以在使用melt的时候指定哪些列用于值:

pd.melt(df, id_vars=['key'], value_vars=['A', 'B'])
key variable value
0 foo A 1
1 bar A 2
2 baz A 3
3 foo B 4
4 bar B 5
5 baz B 6

pandas.melt也能在没有群指示器的情况下使用:

pd.melt(df, value_vars=['A', 'B', 'C'])
variable value
0 A 1
1 A 2
2 A 3
3 B 4
4 B 5
5 B 6
6 C 7
7 C 8
8 C 9
pd.melt(df, value_vars=['key','A', 'B'])
variable value
0 key foo
1 key bar
2 key baz
3 A 1
4 A 2
5 A 3
6 B 4
7 B 5
8 B 6

你可能感兴趣的:(pandas使用教程,pandas,windows,开发语言,python,R,reshape,dataframe)