1.1分层索引
分层索引是pandas的重要特性,允许你在一个轴向上拥有多个(两个或两个以上)索引层级。笼统地说,分层索引提供了一种在更低维度的形式中处理更高维度数据的方式。先创建一个Series,以列表的列表(或数组)作为索引:
data=pd.Series(np.random.randn(9),
index=[['a','a','a','b','b','c','c','d','d'],
[1,2,3,1,3,1,2,2,3]])
print(data)
----------------
a 1 0.211389
2 0.974623
3 0.009878
b 1 1.489891
3 0.097519
c 1 -0.132779
2 -2.556963
d 2 0.296693
3 1.033984
dtype: float64
我们所看到的是一个以MultiIndex作为索引的Series的美化视图。索引中的“间隙”表示“直接使用上面的标签”:
print(data.index)
-----------------------------------------------------------------------------
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
labels=[[0, 0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 2, 0, 1, 1, 2]])
通过分层索引对象,也可以称为部分索引,允许你简洁地选择出数据的子集:
print(data['b'])
-------------
1 -0.295682
3 0.374343
dtype: float64
print(data['b':'c'])
----------------
b 1 -0.295682
3 0.374343
c 1 -1.090632
2 -0.035576
dtype: float64
print(data.loc[['b','d']])
----------------
b 1 -0.295682
3 0.374343
d 2 0.829523
3 -0.374870
dtype: float64
print(data.loc[:,2])
--------------
a 0.395417
c -0.035576
d 0.829523
dtype: float64
分层索引在重塑数据和数组透视表等分组操作中扮演了重要角色。例如,我们可以使用unstack方法将数据在DataFrame中重新排列:
print(data.unstack())
-------------------------------
1 2 3
a 0.248184 -1.516602 0.496004
b -0.382506 NaN -1.534670
c 1.561869 1.890850 NaN
d NaN 1.225667 0.625659
unstack的反操作是stack:
print(data.unstack().stack())
----------------
a 1 -0.355943
2 0.010095
3 -0.856033
b 1 0.136396
3 -1.474994
c 1 -0.008190
2 -0.863610
d 2 -0.034150
3 0.557624
dtype: float64
在DataFrame中,每个轴都可以拥有分层索引:
frame = pd.DataFrame(np.arange(12).reshape((4,3)),index=[['a','a','b','d'],[1,2,1,2]],
columns=[['Ohio','Ohio','Colorado'],
['Green','Red','Green']])
print(frame)
----------------------
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
d 2 9 10 11
分层的层级可以有名称(可以是字符串或python对象)。如果层级有名称,这些名称会在控制台输出中显示:
frame.index.names=['key1','key2']
frame.columns.names=['state','color']
print(frame)
----------------------------
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
d 2 9 10 11
通过部分列索引,我们可以选出列中的组:
print(frame['Ohio'])
---------------------
color Green Red
key1 key2
a 1 0 1
2 3 4
b 1 6 7
d 2 9 10
1.1.1重排序和层级排序
有时,你需要重新排列轴上的层级顺序,或者按照特定层级的值对数据进行排序。swaplevel接收两个层级序号或层级名称,返回一个进行了层级变更的新对象(但是数据都是不变的):
print(frame.swaplevel('key1','key2'))
----------------------------
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 d 9 10 11
另一方面,sort_index只能在单一层级上对数据进行排序。在进行层级变换时,使用sort_index以使得结果按照层级进行字典排序也很常见:
print(frame.sort_index(level=1))
----------------------------
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
b 1 6 7 8
a 2 3 4 5
d 2 9 10 11
print(frame.swaplevel(0,1).sort_index(level=0))
----------------------------
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
b 6 7 8
2 a 3 4 5
d 9 10 11
1.1.2按层级进行汇总统计
DataFrame和Series中很多描述性和汇总性统计有一个level选项,通过level选项你可以指定你想要在某个特定的轴上进行聚合。我们可以按照层级在行或列上像下面这样进行聚合:
print(frame.sum(level='key2'))
------------------------
key2
1 6 8 10
2 12 14 16
print(frame.sum(level='color',axis=1))
---------------------
color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
d 2 20 10
1.1.3使用DataFrame的列进行索引
frame = pd.DataFrame({'a':range(7),'b':range(7,0,-1),
'c':['one','one','one','two','two','two','two'],
'd':[0,1,2,0,1,2,3]})
print(frame)
---------------
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3
DataFrame的set_index函数会生成一个新的DataFrame,新的DataFrame使用一个或多个列作为索引:
frame2=frame.set_index(['c','d'])
print(frame2)
------------
a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
3 6 1
默认情况下这些列会从DataFrame中移除,我们也可以将它们留在DataFrame中:
print(frame.set_index(['c','d'],drop=False))
-------------------
a b c d
c d
one 0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
two 0 3 4 two 0
1 4 3 two 1
2 5 2 two 2
3 6 1 two 3
另一方面,reset_index是set_index的反操作,分层索引的索引层级会被移动到列中:
print(frame2.reset_index())
---------------
c d a b
0 one 0 0 7
1 one 1 1 6
2 one 2 2 5
3 two 0 3 4
4 two 1 4 3
5 two 2 5 2
6 two 3 6 1
1.2联合与合并数据集
包含在pandas对象的数据可以通过多种方式联合在一起:
pandas.merge根据一个或多个键将行进行连接。对于SQL或其他关系型数据库的用户来说,这种方式比较熟悉,它实现的是数据库的连接操作。
pandas.concat使对象在轴向上进行粘合或“堆叠”。
combine_first实例方法允许将重叠的数据拼接在一起,以使用一个对象中的值填充另一个对象中的缺失值。
1.2.1数据库风格的DataFrame连接
合并或连接操作通过一个或多个键连接行来联合数据集。这些操作是关系型数据库的核心内容(例如基于SQL的数据库)。pandas中的merge函数主要用于将各种join操作算法运用在你的数据上:
df1=pd.DataFrame({'key':['b','b','a','c','a','a','b'],
'data1':range(7)})
df2=pd.DataFrame({'key':['a','b','d'],'data2':range(3)})
print(pd.merge(df1,df2))
-------------------
key data1 data2
0 b 0 1
1 b 1 1
2 b 6 1
3 a 2 0
4 a 4 0
5 a 5 0
这里并没有指定在哪一列上进行连接。如果连接的键信息没有指定,merge会自动将重叠列名作为连接的键。但是,显示地连接键才是好的实现:
print(pd.merge(df1,df2,on='key'))
-------------------
key data1 data2
0 b 0 1
1 b 1 1
2 b 6 1
3 a 2 0
4 a 4 0
5 a 5 0
如果每个对象的列名是不同的,你可以分别为它们指定列名:
df3=pd.DataFrame({'lkey':['b','b','a','c','a','a','b'],
'data1':range(7)})
df4=pd.DataFrame({'rkey':['a','b','d'],
'data2':range(3)})
print(pd.merge(df3,df4,left_on='lkey',right_on='rkey'))
-------------------------
lkey data1 rkey data2
0 b 0 b 1
1 b 1 b 1
2 b 6 b 1
3 a 2 a 0
4 a 4 a 0
5 a 5 a 0
默认情况下,merge做的是内连接(‘inner’join),结果中的键是两张表的交集。外连接(outer join)是键的并集,联合了左连接和右连接的效果:
print(pd.merge(df1,df2,how='outer'))
-------------------
key data1 data2
0 b 0.0 1.0
1 b 1.0 1.0
2 b 6.0 1.0
3 a 2.0 0.0
4 a 4.0 0.0
5 a 5.0 0.0
6 c 3.0 NaN
7 d NaN 2.0
表1-1:how参数的不同连接类型
选项 | 行为 |
---|---|
‘inner’ | 只对两张表都有的键的交集进行联合 |
‘left’ | 对所有左表的键进行联合 |
‘right’ | 对所有右表的键进行联合 |
‘outer’ | 对两张表都有的键的并集进行联合 |
df1=pd.DataFrame({'key':['b','b','a','c','a','b'],
'data1':range(6)})
df2=pd.DataFrame({'key':['a','b','a','b','d'],
'data2':range(5)})
print(df1)
------------
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 b 5
print(df2)
------------
key data2
0 a 0
1 b 1
2 a 2
3 b 3
4 d 4
print(pd.merge(df1,df2,on='key',how='left'))
--------------------
key data1 data2
0 b 0 1.0
1 b 0 3.0
2 b 1 1.0
3 b 1 3.0
4 a 2 0.0
5 a 2 2.0
6 c 3 NaN
7 a 4 0.0
8 a 4 2.0
9 b 5 1.0
10 b 5 3.0
多对多连接是行的笛卡尔积。由于在左边的DataFrame中三个‘b’行,而在右边有两行,因此在结果中有六个‘b’行。连接方法仅影响结果中显示的不同键值:
print(pd.merge(df1,df2,how='inner'))
-------------------
key data1 data2
0 b 0 1
1 b 0 3
2 b 1 1
3 b 1 3
4 b 5 1
5 b 5 3
6 a 2 0
7 a 2 2
8 a 4 0
9 a 4 2
使用多个键进行合并时,传入一个列名的列表:
left=pd.DataFrame({'key1':['foo','foo','bar'],
'key2':['one','two','one'],
'lval':[1,2,3]})
right=pd.DataFrame({'key1':['foo','foo','bar','bar'],
'key2':['one','one','one','two'],
'rval':[4,5,6,7]})
print(pd.merge(left,right,on=['key1','key2'],how='outer'))
-----------------------
key1 key2 lval rval
0 foo one 1.0 4.0
1 foo one 1.0 5.0
2 foo two 2.0 NaN
3 bar one 3.0 6.0
4 bar two NaN 7.0
表1-2:merge函数参数
参数 | 描述 |
---|---|
left | 合并时操作中左边的DataFrame |
right | 合并时操作中右边的DataFrame |
how | ‘inner’,‘outer’,‘left’,‘right’之一,默认是’inner’ |
on | 需要连接的列名。必须是在两边的DataFrame对象都有的列名,并以left和right中的列名的交集作为连接键 |
left_on | left DataFrame中用作连接键的列 |
right_on | right DataFrame中用作连接的列 |
left_index | 使用left的行索引作为它的连接键 |
right_index | 使用right的行索引作为它的连接键 |
sort | 通过连接键按字母顺序对合并的数据进行排序;在默认情况下为True |
suffixes | 在重叠情况下,添加到列名后的字符串元祖,默认是(‘_x’,’_y’) |
copy | 默认是False,则在某些特殊情况下避免将数据复制到结果数据结构中 |
1.2.2根据索引合并
在某些情况下,DataFrame中用于合并的键是它的索引。在这种情况下,你可以传递left_index=True或right_index=True(或者都传)来表示索引需要用来作为合并的键:
left1=pd.DataFrame({'key':['a','b','a','a','b','c'],
'value':range(6)})
right1=pd.DataFrame({'group_val':[3.7,7]},index=['a','b'])
print(left1)
------------
key value
0 a 0
1 b 1
2 a 2
3 a 3
4 b 4
5 c 5
print(right1)
------------
group_val
a 3.7
b 7.0
print(pd.merge(left1,right1,left_on='key',right_index=True))
-----------------------
key value group_val
0 a 0 3.7
2 a 2 3.7
3 a 3 3.7
1 b 1 7.0
4 b 4 7.0
由于默认的合并方法是连接键相交,我们也可以使用外连接来进行合并:
print(pd.merge(left1,right1,left_on='key',right_index=True,how='outer'))
-----------------------
key value group_val
0 a 0 3.7
2 a 2 3.7
3 a 3 3.7
1 b 1 7.0
4 b 4 7.0
5 c 5 NaN
在多层索引数据的情况下,事情会更复杂,在索引上连接是一个隐式的多键合并:
lefth=pd.DataFrame({'key1':['Ohio','Ohio','Ohio','Nevada','Neveda'],
'key2':[2000,2001,2002,2001,2002],
'data':np.arange(5.)})
righth=pd.DataFrame(np.arange(12).reshape((6,2)),
index=[['Nevada','Nevada','Ohio','Ohio','Ohio','Ohio'],
[2001,2000,2000,2000,2001,2002]],
columns=['event1','event2'])
print(lefth)
---------------------
key1 key2 data
0 Ohio 2000 0.0
1 Ohio 2001 1.0
2 Ohio 2002 2.0
3 Nevada 2001 3.0
4 Neveda 2002 4.0
print(righth)
---------------------------
event1 event2
Nevada 2001 0 1
2000 2 3
Ohio 2000 4 5
2000 6 7
2001 8 9
2002 10 11
这种情况下,必须以列表的方式指明合并所需多个列:
print(pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True))
---------------------------
event1 event2
Nevada 2001 0 1
2000 2 3
Ohio 2000 4 5
2000 6 7
2001 8 9
2002 10 11
print(pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True,how='outer'))
---------------------------
event1 event2
Nevada 2001 0 1
2000 2 3
Ohio 2000 4 5
2000 6 7
2001 8 9
2002 10 11
使用两边的索引进行合并也是可以的:
left2=pd.DataFrame([[1.,2.],[3.,4.],[5.,6.]],
index=['a','c','e'],
columns=['Ohio','Nevada'])
right2=pd.DataFrame([[7.,8.],[9.,10.],[11.,12.],[13,14]],index=['b','c','d','e'],columns=['Missouri','Alabama'])
print(left2)
---------------
Ohio Nevada
a 1.0 2.0
c 3.0 4.0
e 5.0 6.0
print(right2)
--------------------
Missouri Alabama
b 7.0 8.0
c 9.0 10.0
d 11.0 12.0
e 13.0 14.0
print(pd.merge(left2,right2,how='outer',left_index=True,right_index=True))
----------------------------------
Ohio Nevada Missouri Alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
DataFrame有一个方便的join实例方法,用于按照索引合并。该方法也可以用于合并多个索引相同或相似但没有重叠列的DataFrame对象。在之前的例子中,我们可以这样写:
print(left2.join(right2,how='outer'))
----------------------------------
Ohio Nevada Missouri Alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
最后,对于一些简单索引-索引合并,我们可以向join方法传入一个DataFrame列表:
another=pd.DataFrame([[7.,8.],[9.,10.],[11.,12.],[16.,17.]],
index=['a','c','e','f'],
columns=['New York','Oregon'])
print(another)
-------------------
New York Oregon
a 7.0 8.0
c 9.0 10.0
e 11.0 12.0
f 16.0 17.0
print(left2.join([right2,another]))
----------------------------------------------------
Ohio Nevada Missouri Alabama New York Oregon
a 1.0 2.0 NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0 9.0 10.0
e 5.0 6.0 13.0 14.0 11.0 12.0
print(left2.join([right2,another],how='outer'))
----------------------------------------------------
Ohio Nevada Missouri Alabama New York Oregon
a 1.0 2.0 NaN NaN 7.0 8.0
b NaN NaN 7.0 8.0 NaN NaN
c 3.0 4.0 9.0 10.0 9.0 10.0
d NaN NaN 11.0 12.0 NaN NaN
e 5.0 6.0 13.0 14.0 11.0 12.0
f NaN NaN NaN NaN 16.0 17.0
1.2.3沿轴向连接
另一种数据组合操作可互换地称为拼接、绑定或堆叠。NumPy的concatenate函数可以在NumPy数组上实现该功能:
arr=np.arange(12).reshape((3,4))
print(arr)
--------------
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
print(np.concatenate([arr,arr],axis=1))
--------------------------
[[ 0 1 2 3 0 1 2 3]
[ 4 5 6 7 4 5 6 7]
[ 8 9 10 11 8 9 10 11]]
下面来介绍pandas的concat函数:
s1=pd.Series([0,1],index=['a','b'])
s2=pd.Series([2,3,4],index=['c','d','e'])
s3=pd.Series([5,6],index=['f','g'])
print(pd.concat([s1,s2,s3]))
------------
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
也可以传递一个参数axis=1,返回的结果则是一个DataFrame:
print(pd.concat([s1,s2,s3],axis=1))
----------------
0 1 2
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
s4=pd.concat([s1,s3])
print(s4)
------------
a 0
b 1
f 5
g 6
dtype: int64
print(pd.concat([s1,s4],axis=1))
---------
0 1
a 0.0 0
b 1.0 1
f NaN 5
g NaN 6
print(pd.concat([s1,s4],axis=1,join='inner'))
-------
0 1
a 0 0
b 1 1
在这里也可以使用join_axes来指定用于连接其他轴向的轴:
print(pd.concat([s1,s4],axis=1,join_axes=[['a','c','b','e']]))
-----------
0 1
a 0.0 0.0
c NaN NaN
b 1.0 1.0
e NaN NaN
我们可以用keys参数在连接轴上创建一个多层索引:
result=pd.concat([s1,s1,s3],keys=['one','two','three'])
print(result)
-------------
one a 0
b 1
two a 0
b 1
three f 5
g 6
dtype: int64
print(result.unstack())
-------------------------
a b f g
one 0.0 1.0 NaN NaN
two 0.0 1.0 NaN NaN
three NaN NaN 5.0 6.0
沿着轴向axis=1连接Series的时候,keys则成为DataFrame的列头:
print(pd.concat([s1,s2,s3],axis=1,keys=['one','two','three']))
------------------
one two three
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
将相同的逻辑拓展到DataFrame对象:
df1=pd.DataFrame(np.arange(6).reshape(3,2),index=['a','b','c'],columns=['one','two'])
df2=pd.DataFrame(5+np.arange(4).reshape(2,2),index=['a','c'],columns=['three','four'])
print(df1)
-----------
one two
a 0 1
b 2 3
c 4 5
print(df2)
--------------
three four
a 5 6
c 7 8
print(pd.concat([df1,df2],axis=1,keys=['level1','level2']))
------------------------
level1 level2
one two three four
a 0 1 5.0 6.0
b 2 3 NaN NaN
c 4 5 7.0 8.0
如果传递的是对象的字典而不是列表的话,则字典的键会用于keys选项:
print(pd.concat({'level1':df1,'level2':df2},axis=1))
------------------------
level1 level2
one two three four
a 0 1 5.0 6.0
b 2 3 NaN NaN
c 4 5 7.0 8.0
我们可以用names参数命名生成的轴层级:
print(pd.concat([df1,df2],axis=1,keys=['level1','level2'],names=['upper','lower']))
----------------------------
upper level1 level2
lower one two three four
a 0 1 5.0 6.0
b 2 3 NaN NaN
c 4 5 7.0 8.0
表1-3:concat函数的参数
参数 | 描述 |
---|---|
objs | 需要连接的pandas对象列表或字典;这是必选参数 |
axis | 连接的轴向;默认是1 |
join | 可以是’inner’或’outer’;用于指定连接方式是内连接还是外连接 |
keys | 与要连接的对象关联的值,沿着连接轴形成分层索引;可以是任意值的列表或数组,也可以是元祖的数组,也可以是数组的列表(如果向levels参数传入多层数组) |
names | 如果传入了keys或levels参数,该参数用于多层索引的层级名称 |
ignore_index | 不沿着连接轴保留索引,而产生一段新的索引 |
1.2.4联合重叠数据
还有另一个数据联合场景,既不是合并操作,也不是连接操作。你可能有两个数据集,这两个数据集的索引全部或部分重叠。作为一个示例,考虑NumPy的where函数,这个函数可以进行面向数组的if-else等价操作:
a=pd.Series([np.nan,2.5,0.0,3.5,4.5,np.nan],index=['f','e','d','c','b','a'])
b=pd.Series([0.,np.nan,2.,np.nan,np.nan,5.])
print(a)
--------------
f NaN
e 2.5
d 0.0
c 3.5
b 4.5
a NaN
dtype: float64
print(b)
--------------
0 0.0
1 NaN
2 2.0
3 NaN
4 NaN
5 5.0
dtype: float64
print(np.where(pd.isnull(a),b,a))
-------------------------
[0. 2.5 0. 3.5 4.5 5. ]
在DataFrame中,combine_first逐列做相同的操作,因此我们可以认为它是根据传入的对象来“修补”调用对象的缺失值:
df1=pd.DataFrame({'a':[1.,np.nan,5.,np.nan],
'b':[np.nan,2.,np.nan,6.],
'c':range(2,18,4)})
df2=pd.DataFrame({'a':[5.,4.,np.nan,3.,7.],
'b':[np.nan,3.,4.,6.,8.]})
print(df1)
---------------
a b c
0 1.0 NaN 2
1 NaN 2.0 6
2 5.0 NaN 10
3 NaN 6.0 14
print(df2)
-----------
a b
0 5.0 NaN
1 4.0 3.0
2 NaN 4.0
3 3.0 6.0
4 7.0 8.0
print(df1.combine_first(df2))
-----------------
a b c
0 1.0 NaN 2.0
1 4.0 2.0 6.0
2 5.0 4.0 10.0
3 3.0 6.0 14.0
4 7.0 8.0 NaN
1.3重塑和透视
重排列表格型数据有多种基础操作。这些操作被称为重塑或透视。
1.3.1使用多层索引进行重塑
多层索引在DataFrame中提供了一种一致性方式用于重排列数据。以下是基础操作:
stack(堆叠)
该操作会“旋转”或将列中的数据透视到行。
unstack(拆堆)
该操作会将行中的数据透视到列。
下面考虑一个带有字符串数组作为行或列索引的小型DataFrame:
data=pd.DataFrame(np.arange(6).reshape((2,3)),index=pd.Index(['Ohio','Colorado'],name='state'),columns=pd.Index(['one','two','three'],name='number'))
print(data)
-------------------------
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
在这份数据上使用stack方法会将列透视到行,产生一个新的Series:
result=data.stack()
print(result)
---------------------
state number
Ohio one 0
two 1
three 2
Colorado one 3
two 4
three 5
dtype: int32
从一个多层索引序列中,我们可以使用unstack方法将数据重排列后放入一个DataFrame中:
print(result.unstack())
-------------------------
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
默认情况下,最内层是已拆堆的(与stack方法一样)。你可以传入一个层级序号或名称来拆分一个不同的层级:
print(result.unstack(0))
----------------------
state Ohio Colorado
number
one 0 3
two 1 4
three 2 5
print(result.unstack('state'))
----------------------
state Ohio Colorado
number
one 0 3
two 1 4
three 2 5
如果层级中的所有值并未包含于每个子分组中时,拆分可能会引入缺失值:
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'])
print(data2)
------------
one a 0
b 1
c 2
d 3
two c 4
d 5
e 6
dtype: int64
print(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
默认情况下,堆叠会过滤出缺失值,因此堆叠拆堆的操作是可逆的:
print(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
print(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
print(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中拆堆时,被拆堆的层级会变为结果中最低的层级:
df=pd.DataFrame({'left':result,'right':result+5},
columns=pd.Index(['left','right'],name='side'))
print(df)
----------------------------
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
print(df.unstack('state'))
-----------------------------------
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方法时,我们可以指明需要堆叠的轴向名称:
print(df.unstack('state').stack('side'))
----------------------------
state Colorado Ohio
number side
one left 3 0
right 8 5
two left 4 1
right 9 6
three left 5 2
right 10 7