1. 写在前面
今天总结一下pandas的四个函数, stack, unstack, melt和pivot, 这四个函数再处理DataFrame结构的时候, 非常常用, 也非常好用, 具体的就来看一下。
pd.stack()和pd.unstack()
这两个方法在数据分析的时候也是非常常用, 网上的文档说这是行转列,列转行的方法,但是具体转的时候,还是不知道转过来会是什么样子,或者有了需求也不会用,所以在这里,记录一下我对这两个方法的理解。
方法原型: 通过 ?pd.DataFrame.unstack/stack
来查看具体的描述:
- pd.DataFrame.stack(self, level=-1, dropna=True)
- pd.DataFrame.unstack(self, level=-1, fill_value=None)
这里我们先构造一个简单的数据出来, 然后看一下这两个函数到底把DataFrame变成了什么结构。
# 先构造一个简单的数据出来
d1 = sales_data[0:1]
d2 = sales_data[20000:20001]
d3 = sales_data[25000:25001]
select = pd.concat([d1, d2, d3]).reset_index()
del select['index']
col = ['cat_id', 'state_id', 'd_1']
select = select[col]
select
构造出来的DataFrame结构长这样:
其实就是普通的数据了。 下面我们用unstack()
看看效果:
再来看看stack()
的效果:
下面解释一下到底是怎么变的, 先上图:
简单的来理解, 如果我们的数据是表格的形式,stack之后,会变成左边这种花括号的形式,而变的时候, 可以发现原来表格里面的列索引变成了行索引的子索引, 而如果表格数据直接unstack之后, 会发现原来表格里面的列索引变成了行索引的父索引。
子索引和父索引用花括号来理解简单一点,这个描述可能不准确,但是好理解,并且能迅速想出变换之后的样子。 上面的例子见下图:并且这样理解的话,对于多层索引,指定了level下的情况也非常简单:
这时候, 我们用stack(), 关键句:列索引变成了行索引的子索引
这里的level默认是由内而外,所以stack的时候,是把第二层的列索引当成了行索引的子索引。 由于列索引有两层,所以这里的level可以取0,表示外层列索引作为行索引的子索引, 1表示内层列索引作为行索引的子索引。不信,指定一下level=0试试。
当然还可以指定level为[0,1],表示这俩列索引都当做行索引的子索引。
下面我们再看unstack()

是不是两级列索引都成了行索引的父索引? 且默认就是两层都变过去。 如果指定level, 也不起作用了, 貌似把两个列索引看成整体了。但是如果是从花括号unstack的话,level就起作用了。 我们看看上面stack后的那个Series:如果使用unstack,就会逆回去。 但是根据指定的level不同,变成的数据不一样。一般我们用的时候,不是单纯的unstack
或者stack
,而是还要reset_index
一下,变成DataFrame数据。
这种结构的变换有时候会很有用的。所以可以了解一下。
pd.melt()函数
函数原型:
pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name=‘value’, col_level=None)
参数解释:
- frame:要处理的数据集。
- id_vars:不需要被转换的列名。
- value_vars:需要转换的列名,如果剩下的列全部都要转换,就不用写了。
- var_name和value_name是自定义设置对应的列名。
- col_level :如果列是MultiIndex,则使用此级别。
这个方法,类似stack,也可以实现列转行。 但是会更加灵活, 可以指定那些列变或者不变,还可以给列重新命名,也不同reset_index,非常适合把宽数据变成长数据
pd.pivot()函数
这个就是根据列值重塑数据(生成一个“透视”表)。使用来自索引/列的惟一值来形成结果数据流的轴。
函数原型:
DataFrame.pivot(index=None, columns=None, values=None)[source]
比如: