长宽表转换就是将比较长(很多行)的表转换为比较宽(很多列)的表,或者将比较宽的表转换为比较长的表
下表是一个宽表
转换后的长表如图所示
上面这种由很多列转换为很多行的过程,就是宽表转换为长表的过程,这种转换过程是有前提的, 那就是需要有公共列
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系列之数据透视表 一文