数据分析学习笔记之连接、联合与重塑

314 阅读16分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」。

1.分层索引

分层索引是pandas的重要特性,允许在一个轴向上拥有多个(两个或两个以上)索引层级。

  • 分层索引在重塑数据和数组透视表等分组操作中扮演了重要角色,例如,可以使用unstack方法将数据在DataFrame中重新排列;

  • unstack的反操作是stack

  • 在DataFrame中,每个轴都可以拥有分层索引:

    frame = pd.DataFrame(np.arange(12).reshape((4, 3)), index = [['a', 'a', 'b', 'b'], [1, 2, 1, 2]], columns = [['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']])
    frame
    [out]
    			Ohio	Ohio	Colorado
    			Green	Red		Green
    a	1		0		1		2
    	2		3		4		5
    b	1		6		7		8
    	2		9		10		11
    
  • 分层的层级可以有名称(可以是字符串或Python对象)。如果层级有名称,这些名称会在控制台输出中显示:

    frame.index.names = ['key1', 'key2']
    frame.columns.names = ['state', 'color']
    frame
    [out]
    		state	Ohio	Ohio	Colorado
    		color	Green	Red		Green
    key1	key2			
    a		1		0		1		2
    		2		3		4		5
    b		1		6		7		8
    		2		9		10		11
    
  • 一个MultiIndex对象可以使用其自身的构造函数创建并复用。

1.1 重排序和层级排序

应用场景:需要重新排列轴上的层级顺序,或者按照特定层级的值对数据进行排序。

  • swaplevel接收两个层级序号或层级名称,返回一个进行了层级变更的新对象(数据是不变的)
  • sort_index只能在单一层级上对数据进行排序,在进行层级变换时,可以使用sort_index以使得结果按照层级进行字段排序;
  • 如果索引按照字典顺序从最外层开始排序,那么数据选择性能会更好-调用sort_index(level = 0)sort_index可以得到这样的结果。

1.2 按照层级进行汇总统计

DataFrame和Series中很多描述性和汇总性统计有一个level选项,通过level选项可以指定某个特定轴进行聚合(默认是行,设置axis = 1就是在列上进行聚合)。

1.3 使用DataFrame的列进行索引

使用场景:通常不会使用DataFrame中的一个或多个列作为索引,反而是将行索引移到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]})
frame
[out]

	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'])
    frame2
    [out]
    		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中(设置参数drop = False即可):

    frame.set_index(['c', 'd'], drop = False)
    [out]
    		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的反操作,分层索引的索引层会被移动到列中:

    frame2.reset_index()
    [out]
    	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
    

2.联合与合并数据集

包含在pandas对象的数据可以通过多种方式联合在一起:

  • pandas.merge:根据一个或多个键将行进行连接,对于SQL或其他关系型数据库的用户来说,这种方式比较熟悉,它实现的是数据库的连接操作;
  • pandas.concat:使对象在轴向上进行黏合或“堆叠”;
  • combine_first:该实例方法允许将重叠的数据拼接在一起,以使用一个对象中的值填充另一个对象中的缺失值。

2.1 数据库风格的DataFrame连接

合并或连接操作通过一个或多个键连接行来联合数据集,pandas中的merge函数主要用于将各种join操作算法运用到数据上。

  • 用法:pd.merge(df1, df2);

  • 如果连接的键信息没有指定,merge会自动将重叠列名作为连接的键,但显式地指定连接键才是好的实现:设置参数on = 用于连接的键名;

  • 如果每个对象的列名是不同的,可以分别为它们指定列名(指定参数left_on和right_on的值);

    df3 = pd.DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1': range(7)})
    df4 = pd.DataFrame({'rkey': ['a', 'b', 'd'], 'data2': range(3)})
    pd.merge(df3, df4, left_on = 'lkey', right_on = 'rkey')
    [out]
    	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),结果中的键是两张表中的交集,其他可选的选项有'left'、'right'和'outer',外连接(outer join)是键的并集(这些选项可以通过指定参数how的值来实现,缺失值用NaN处理)。

    pd.merge(df1, df2, how = 'outer')
    [out]
    
    	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
    

how选项的总结:

选项行为
'inner'只对两张表都有的键的交集进行联合
'left'对所有左表的键进行联合
'right'对所有右表的键进行联合
'outer'对两张表都有的键的并集进行联合
  • 多对多连接是行的笛卡尔积,连接方法仅影响结果中显示的不同键值;

  • 使用多个键进行合并时,传入一个列名的列表(on = [列名列表]):

    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]})
    pd.merge(left, right, on = ['key1', 'key2'], how = 'outer')
    [out]
    	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
    
  • 要决定哪些键联合出现在结果中,取决于合并方法的选择,把多个键看作一个元组数据来作为单个连接键使用;

  • 当在进行列-列连接时,传递的DataFrame索引对象会被丢弃;

  • 合并操作中如何处理重叠的列名:merge有一个suffixes后缀选项,用于在左右两边DataFrame对象的重叠列名后指定需要添加的字符串:

    pd.merge(left, right, on = 'key1', suffixes = ('_left', '_right'))
    [out]
    	key1	key2_left	lval	key2_right	rval
    0	foo		one			1		one			4
    1	foo		one			1		one			5
    2	foo		two			2		one			4
    3	foo		two			2		one			5
    4	bar		one			3		one			6
    5	bar		one			3		two			7
    

merge函数参数

参数描述
left合并操作中左边的DataFrame
right合并操作中右边的DataFrame
how'inner'、'outer'、'left'、'right'之一,默认是'inner'
on需要连接的列名,必须是在两边的DataFrame对象都有的列名,并以left和right中的列名的交集作为连接键
left_onleft DataFrame中用作连接键的列
right_onright DataFrame中用作连接键的列
left_index使用left的行索引作为它的连接键(如果是MultiIndex,则是多个键)
right_index使用right的行索引作为它的连接键(如果是MultiIndex,则是多个键)
sort通过连接键按字母顺序对合并的数据进行排序,在默认情况下为True
suffixes在重叠情况下,添加到列名后的字符串元组,默认是('_x', '_y')
copy如果为False,则在某些特殊情况下避免将数据复制到结果数据结构中,默认情况下总是复制
indicator添加一个特殊的列_merge,指示每一行的来源,值将根据每行中连接数据的来源分别为'left_only','right_only'或'both'

2.2 根据索引合并

在某些情况下,DataFrame中用于合并的键是它的索引。在这种情况下,可以传递left_index = True或right_index = True(或者两者都传)来表示索引需要用来作为合并的键:

left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'], 'value': range(6)})
left1
[out]
	key	value
0	a	0
1	b	1
2	a	2
3	a	3
4	b	4
5	c	5

right1 = pd.DataFrame({'group_val': [3.5, 7]}, index = ['a', 'b'])
right1
[out]
	group_val
a	3.5
b	7.0

pd.merge(left1, right1, left_on = 'key', right_index = True)
[out]
	key	value	group_val
0	a	0		3.5
2	a	2		3.5
3	a	3		3.5
1	b	1		7.0
4	b	4		7.0
  • 默认的合并方法是连接键相交,可以使用外连接来进行合并;

    pd.merge(left1, right1, left_on = 'key', right_index = True, how = 'outer')
    [out]
    	key	value	group_val
    0	a	0		3.5
    2	a	2		3.5
    3	a	3		3.5
    1	b	1		7.0
    4	b	4		7.0
    5	c	5		NaN
    
  • 在多层索引数据的情况下,索引上连接是一个隐式的多键合并,这种情况下,必须以列表的方式指明合并所需多个列(注意需使用how = 'outer'处理重复的索引值);

    lefth = pd.DataFrame({'key1': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'key2': [2000, 2001, 2002, 2001, 2002], 'data': np.arange(5.)})
    lefth
    [out]
    	key1	key2	data
    0	Ohio	2000	0.0
    1	Ohio	2001	1.0
    2	Ohio	2002	2.0
    3	Nevada	2001	3.0
    4	Nevada	2002	4.0
    
    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'])
    righth
    [out]
    				event1	event2
    Nevada	2001	0		1
    		2000	2		3
    Ohio	2000	        4		5
    		2000	6		7
    		2001	8		9
    		2002	10		11
            
    pd.merge(lefth, righth, left_on = ['key1', 'key2'], right_index = True, how = 'outer')
    [out]
    	key1	key2	data	event1	event2
    0	Ohio	2000	0.0		4.0		5.0
    0	Ohio	2000	0.0		6.0		7.0
    1	Ohio	2001	1.0		8.0		9.0
    2	Ohio	2002	2.0		10.0	        11.0
    3	Nevada	2001	3.0		0.0		1.0
    4	Nevada	2002	4.0		NaN		NaN
    4	Nevada	2000	NaN		2.0		3.0
    
  • 使用两边的索引进行合并(left_index和right_index均设置为True);

    left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]], index = ['a', 'c', 'e'], columns = ['Ohio', 'Nevada'])
    left2
    [out]
    	Ohio	Nevada
    a	1.0		2.0
    c	3.0		4.0
    e	5.0		6.0
    
    right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13., 14.]], index = ['b', 'c', 'd', 'e'], columns = ['Missouri', 'Alabama'])
    right2
    [out]
    	Missouri	Alabama
    b	7.0		8.0
    c	9.0		10.0
    d	11.0		12.0
    e	13.0		14.0
    
    pd.merge(left2, right2, how = 'outer', left_index = True, right_index = True)
    [out]
    	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		3.0			14.0
    
  • DataFrame有一个方便的join实例方法,用于按照索引合并,该方法也可以用于合并多个索引相同或相似但没有重叠列的DataFrame对象;

    left2.join(right2, how = 'outer')
    [out]
    		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的行索引,它还支持在调用DataFrame的某一列上连接传递的DataFrame的索引;

    left1.join(right1, on = 'key')
    [out]
    	key	value	group_val
    0	a	0		3.5
    1	b	1		7.0
    2	a	2		3.5
    3	a	3		3.5
    4	b	4		7.0
    5	c	5		NaN
    
  • 对于一些简单索引-索引合并,可以向join方法传入一个DataFrame列表。

    another = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],index = ['a', 'c', 'e', 'f'], columns = ['New York', 'Oregon'])
    another
    [out]
    	New York	Oregon
    a	7.0		8.0
    c	9.0		10.0
    e	11.0		12.0
    f	16.0		17.0
    
    left2.join([right2, another], how = 'outer')
    [out]
    	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
    b	NaN		NaN		7.0			8.0		NaN			NaN
    d	NaN		NaN		11.0		12.0	NaN			NaN
    f	NaN		NaN		NaN			NaN		16.0		17.0
    

2.3 沿轴向连接

另一种数据组合操作可互换地称为拼接、绑定或堆叠。NumPy的concatenate函数可以在NumPy数组上实现该功能。

  • 在Series和DataFrame等pandas对象的上下文中,使用标记的轴可以进一步泛化数组连接。

考虑以下几种情况:

  • 如果对象在其他轴上的索引不同,是否应该将不同的元素组合在这些轴上,还是只使用共享的值(交集)?
  • 连接的数据块是否需要在结果对象中被识别?
  • “连接轴”是否包含需要保存的数据?(在很多情况下,DataFrame中的默认整数标签在连接期间最好丢弃)

pandas的concat函数提供了一种一致性的方式来解决上述问题。

假设有三个索引不存在重叠的Series:

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'])

用列表中的这些对象调用concat方法会将值和索引粘在一起:

pd.concat([s1, s2, s3])
[out]
a    0
b    1
c    2
d    3
e    4
f    5
g    6
dtype: int64
  • 默认情况下,concat方法是沿着axis = 0的轴向生效的,生成另一个Series,如果传递axis = 1,返回的结果则是一个DataFrame:

    pd.concat([s1, s2, s3], axis = 1)
    [out]
    	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
    
  • 传入join = 'inner'可以处理重叠标签:

    s4 = pd.concat([s1, s3])
    s4
    [out]
    a    0
    b    1
    f    5
    g    6
    dtype: int64
    
    pd.concat([s1, s4], axis = 1)
    [out]
    	0	1
    a	0.0	0
    b	1.0	1
    f	NaN	5
    g	NaN	6
    
    pd.concat([s1, s4], axis = 1, join = 'inner')
    [out]
    	0	1
    a	0	0
    b	1	1
    
  • 拼接在一起的各部分无法在结果中区分的问题:可以使用keys参数来解决:

    result = pd.concat([s1, s2, s3], keys = ['one', 'two', 'three'])
    result
    [out]
    one    a    0
           b    1
    two    c    2
           d    3
           e    4
    three  f    5
           g    6
    dtype: int64
    
  • 沿着轴向axis = 1连接Series时,keys则成为DataFrame的列头:

    pd.concat([s1, s2, s3], axis = 1, keys = ['one', 'two', 'three'])
    [out]
    
    	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对象(这里的keys与前面的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'])
    pd.concat([df1, df2], axis = 1, keys = ['level1', 'level2'])
    [out]
    	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选项:

    pd.concat({'level3': df1, 'level4': df2}, axis = 1)
    [out]
    	level3			level4
    	one		two		three	four
    a	0		1		5.0		6.0
    b	2		3		NaN		NaN
    c	4		5		7.0		8.0
    
  • 还有一些额外的参数负责多层索引生成,例如,可以使用Names参数命名生成的轴层级:

    pd.concat([df1, df2], axis = 1, keys = ['level1', 'level2'], names = ['upper', 'lower'])
    [out]
    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
    
  • 还有一种需要考虑的情况,就是行索引中不包含任何相关数据的DataFrame(即没有指定index的值,指定参数ignore_index = True):

    pd.concat([df1, df2], ignore_index = True)
    [out]
    	a			b			c			d
    0	1.438888	-0.058913	-0.014392	-1.385697
    1	0.994368	1.167432	-1.793285	0.460772
    2	-0.824447	0.577400	1.270614	-1.108228
    3	-1.528036	0.625684	NaN			0.964432
    4	-0.422344	0.973821	NaN			-2.203932
    

concat函数的参数

参数描述
objs需要连接的pandas对象列表或字典,这是必选参数
axis连接的轴向,默认是0(沿着行方向)
join可以是'inner'或'outer'(默认是'outer'),用于指定连接方式是内连接还是外连接
join_axes用于指定其他n - 1轴的特定索引,可以替代内/外连接的逻辑
keys与要连接的对象关联的值,沿着连接轴形成分层索引,可以是任意值的列表或数组,也可以是元组的数组,也可以是数组的列表(如果向levels参数传入多层数组)
levels在键值传递时,该参数用于指定多层索引的层级
names如果传入了keys和/或levels参数,该参数用于多层索引的层级名称
verify_integrity检查连接对象中的新轴是否重复,如果是,则引发异常,默认(False)允许重复
ignore_index不沿着连接轴保留索引,而产生的一段新的(长度为total_length)索引

2.4 联合重叠数据

  • NumPy的where函数,这个函数可以进行面向数组的if-else等价操作(np.where(condition, x, y),满足条件输出x,不满足输出y):

    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.], index = ['a', 'b', 'c', 'd', 'e', 'f'])
    a
    [out]
    f    NaN
    e    2.5
    d    0.0
    c    3.5
    b    4.5
    a    NaN
    dtype: float64
        
    b
    [out]
    a    0.0
    b    NaN
    c    2.0
    d    NaN
    e    NaN
    f    5.0
    dtype: float64
        
    np.where(pd.isnull(a), b, a)
    [out]
    array([0. , 2.5, 0. , 3.5, 4.5, 5. ])
    
  • Series有一个combine_first方法,该方法可以等价于下面这种使用pandas常见数据对齐逻辑的轴向操作(combine_first:将前者为np.nan的用后者相同位置的数来补充,相当于打补丁):

    b.combine_first(a)
    [out]
    b.combine_first(a)
    b.combine_first(a)
    a    0.0
    b    4.5
    c    2.0
    d    0.0
    e    2.5
    f    5.0
    dtype: float64
    
  • 在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)})
    df1
    [out]
    	a	b	c
    0	1.0	NaN	2
    1	NaN	2.0	6
    2	5.0	NaN	10
    3	NaN	6.0	14
    
    df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.], 'b': [np.nan, 3., 4., 6., 8.]})
    df2
    [out]
    	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
    
    df1.combine_first(df2)
    [out]
    	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
    

3.重塑和透视

3.1 使用多层索引进行重塑

多层索引在DataFrame中提供了一种一致性方式用于重排列数据,以下是两个基础操作:

  • stack(堆叠):该操作会“旋转”或将列中的数据透视到行;

  • unstack(拆堆):该操作会将行中的数据透视到列;

  • 数据透视的概念:在交叉表中将行旋转成列和将列旋转成行;

  • 对一个DataFrame使用stack()方法会产生一个新的Series对象,对该对像再使用unstack()方法会将数据重排列后放入一个DataFrame中;

  • 默认情况下,最内层是已拆堆的(与stack方法一样),可以传入一个层级序号或名称来拆分一个不同的层级:

  • 如果层级中的所有值并未包含于每个子分组中,拆分可能会引入缺失值:

1.png

  • 默认情况下,堆叠会过滤出缺失值,因此堆叠拆堆的操作是可逆的:

2.png

  • 当在DataFrame中拆堆时,被拆堆的层级会变为结果中最低的层级:

3.png

  • 在调用stack方法时,可以指明需要堆叠的轴向名称:

4.png

3.2 将“长”透视为“宽”

使用DataFrame的pivot方法。

应用场景:数据通常以键 + 值的形式存在于关系型数据库中,处理这种格式的数据,可能更倾向于获取一个按特定列索引的且每个不同的item独立一列的DataFrame,DataFrame的pivot方法就是进行这种转换的。

先载入一些数据,然后做少量的时间序列归整和其他的数据清洗操作:

  • 读取数据:

5.png

  • 使用PeriodIndex将year和quarter进行联合并生成一种时间间隔类型:

6.png

  • 对data重建索引:

7.png

8.png

  • 生成ldata:

9.png

  • 对ldata使用pivot方法(传递的前两个值分别用作行和列索引的列,然后是可选的数值列以填充DataFrame):

10.png

  • 假设有两个数值列,现在想同时进行重塑:

11.png

  • 如果遗漏最后一个参数(即数值),会得到一个含有多层列的DataFrame(默认取全部的可选数值):

12.png

  • 注意:pivot方法等价于使用set_index创建分层索引,然后调用unstack。

13.png

3.3 将“宽”透视为“长”

在DataFrame中,pivot方法的反操作是pandas.melt。与将一列变换为新的DataFrame中的多列不同,它将多列合并成一列,产生一个新的DataFrame,其长度比输入更长。

  • 准备数据:

14.png

  • 'key'列可以作为分组指标,其他列均为数据值。当使用melt时,必须指明哪些列是分组指标(如果有的话)。此处,使用'key'作为唯一的分组指标:

15.png

  • 使用pivot方法,可以将数据重塑会原先的布局:

16.png

  • 也可以指定列的子集作为值列:

17.png

  • pandas.melt的使用也可以无须任何分组指标:

18.png