pandas教程:Reshaping and Pivoting 整形和旋转-灵析社区

清晨我上码

8.3 Reshaping and Pivoting(整形和旋转)

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

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

使用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()

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

result.unstack(0)

result.unstack('state')

如果某个层级里的值不能在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()

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

data2.unstack()

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这一个层级

df.unstack('state')  # state被unstack后,变为比side更低的层级

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

df.unstack('state').stack('side')

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

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

data = pd.read_csv('../examples/macrodata.csv')
data.head()

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,我们会在第十一章讲得更详细些。在这里,这个函数把year和quarter这两列整合起来作为一种时间间隔类型。

ldata看起来是这样的:

ldata[:10]

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

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

pivoted = ldata.pivot('date', 'item', 'value')
pivoted

203 rows × 3 columns

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

ldata['value2'] = np.random.randn(len(ldata))
ldata[:10]

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

pivoted = ldata.pivot('date', 'item')
pivoted[:5]

pivoted['value'][:5]

这里pivot相当于用set_index创建了一个多层级用里,并调用了unstack:

unstacked = ldata.set_index(['date', 'item']).unstack('item')
unstacked[:7]

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

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

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

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

melted = pd.melt(df, ['key'])
melted

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

reshaped = melted.pivot('key', 'variable', 'value')
reshaped

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

reshaped.reset_index()

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

pd.melt(df, id_vars=['key'], value_vars=['A', 'B'])

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

pd.melt(df, value_vars=['A', 'B', 'C'])

pd.melt(df, value_vars=['key','A', 'B'])

阅读量:566

点赞量:0

收藏量:0