pandas系列之长宽表转换

1,706 阅读5分钟

长宽表转换就是将比较长(很多行)的表转换为比较宽(很多列)的表,或者将比较宽的表转换为比较长的表

下表是一个宽表

image.png

转换后的长表如图所示

image.png 上面这种由很多列转换为很多行的过程,就是宽表转换为长表的过程,这种转换过程是有前提的, 那就是需要有公共列

1 宽表转换为长表

转换之前先来看一下原始的数据结构

import pandas as pd
​
user_df = pd.read_excel(r'C:\Users\viruser.v-desktop\Desktop\用户信息表.xlsx')
print(user_df)

result:

   用户id 等级  区域  城市  7月销量  8月销量  9月销量    分类  编号   名称 用户名
0     1  A  华东  上海    65    67    78    水果   0   苹果  小明
1     2  B  华中  武汉    45    54    58    水果   1   橙子  小明
2     3  B  东北  大连    12    34    46  生活用品   2   牙刷  小明
3     4  D  华南  广东    60    72    78  生活用品   4   冰箱  小刚
4     5  C  华中  长沙    56    67    74  生活用品   4  电视机  小刚

python中有2种实现方法,一种是stack()方法,一种是melt()方法

1.1 stack()方法

该方法在将表格型数据转换为树形数据时,是在保持行索引不变的前提下,将列索引也变成行索引

import pandas as pd
​
user_df = pd.read_excel(r'C:\Users\viruser.v-desktop\Desktop\用户信息表.xlsx')
tmp_df = user_df.set_index(['用户id', '等级', '区域', '城市', '分类', '编号', '名称', '销量', '用户名'])
new_df = tmp_df.stack()
final_df = new_df.reset_index()
final_df.columns = ['用户id', '等级', '区域', '城市', '分类', '编号', '名称', '用户名', "销量的月份", "销量"]
print(final_df)

result:

    用户id 等级  区域  城市    分类  编号   名称 用户名 销量的月份  销量
0      1  A  华东  上海    水果   0   苹果  小明  7月销量  65
1      1  A  华东  上海    水果   0   苹果  小明  8月销量  67
2      1  A  华东  上海    水果   0   苹果  小明  9月销量  78
3      2  B  华中  武汉    水果   1   橙子  小明  7月销量  45
4      2  B  华中  武汉    水果   1   橙子  小明  8月销量  54
5      2  B  华中  武汉    水果   1   橙子  小明  9月销量  58
6      3  B  东北  大连  生活用品   2   牙刷  小明  7月销量  12
7      3  B  东北  大连  生活用品   2   牙刷  小明  8月销量  34
8      3  B  东北  大连  生活用品   2   牙刷  小明  9月销量  46
9      4  D  华南  广东  生活用品   4   冰箱  小刚  7月销量  60
10     4  D  华南  广东  生活用品   4   冰箱  小刚  8月销量  72
11     4  D  华南  广东  生活用品   4   冰箱  小刚  9月销量  78
12     5  C  华中  长沙  生活用品   4  电视机  小刚  7月销量  56
13     5  C  华中  长沙  生活用品   4  电视机  小刚  8月销量  67
14     5  C  华中  长沙  生活用品   4  电视机  小刚  9月销量  74

解释一下,这里将宽表转换为长表首先是要在保持用户id, 等级, 区域, 城市, 分类, 编号, 名称, 销量, 用户名这些列不变的前提下,将7月销量、7月销量、9月销量也变成行索引。所以需要先设置用户id, 等级, 区域, 城市, 分类, 编号, 名称, 销量, 用户名为索引,然后调用stack()方法,将列索引也转换为行索引,最后利用reset_index()方法进行索引重置并对列重命名。

1.2 melt()方法

import pandas as pd
​
​
user_df = pd.read_excel(r'C:\Users\viruser.v-desktop\Desktop\用户信息表.xlsx')
print(user_df.melt(id_vars=['用户id', '等级', '区域', '城市', '分类', '编号', '名称', '销量', '用户名'],
                   var_name='销量的月份', value_name='销量'))

result:

用户id 等级  区域  城市    分类  编号   名称 用户名 销量的月份  销量
​
0      1  A  华东  上海    水果   0   苹果  小明  7月销量  65
1      2  B  华中  武汉    水果   1   橙子  小明  7月销量  45
2      3  B  东北  大连  生活用品   2   牙刷  小明  7月销量  12
3      4  D  华南  广东  生活用品   4   冰箱  小刚  7月销量  60
4      5  C  华中  长沙  生活用品   4  电视机  小刚  7月销量  56
5      1  A  华东  上海    水果   0   苹果  小明  8月销量  67
6      2  B  华中  武汉    水果   1   橙子  小明  8月销量  54
7      3  B  东北  大连  生活用品   2   牙刷  小明  8月销量  34
8      4  D  华南  广东  生活用品   4   冰箱  小刚  8月销量  72
9      5  C  华中  长沙  生活用品   4  电视机  小刚  8月销量  67
10     1  A  华东  上海    水果   0   苹果  小明  9月销量  78
11     2  B  华中  武汉    水果   1   橙子  小明  9月销量  58
12     3  B  东北  大连  生活用品   2   牙刷  小明  9月销量  46
13     4  D  华南  广东  生活用品   4   冰箱  小刚  9月销量  78
14     5  C  华中  长沙  生活用品   4  电视机  小刚  9月销量  74

melt中的id_vars参数用于指明宽表转换为长表时保持不变的列,var_name参数表示原来的列索引转换为"行索引"后对应的列名,value_name表示新索引对应的值的列名。

注意,这里的"行索引"不是真正意义上的行索引,只是类似行索引。

print(final_df.index)

result:

print(final_df.index)

2 长表转换为宽表

将长表转换为宽表就是宽表转换为长表的逆过程,常用的方法就是数据透视表。关于数据透视表参见 pandas系列之数据透视表 一文