如何利用pandas的melt()方法,实现宽表转长表的操作?
发布于 作者:苏南大叔 来源:程序如此灵动~ 我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...
在pandas
里面有一个melt()
方法,操作对象是dataframe
。可以把一部分列数据变成横向的行数据。这个列变成行的效果,转换的也并不完全。这个函数的主要功能是把部分列数据变成行数据,也有部分列数据保持不变。同时也会有数据增生的现象发生,原列标签会变成主体内容,同时生成新的列标签。总之,就是和行列互换的需求是完全不同的结果。
大家好,这里是苏南大叔的"程序如此灵动"博客,本文记录pandas
的melt()
方法。测试环境:win10
,python@3.11.0
,numpy@1.24.2
,pandas@1.5.3
。而且这个melt()
函数还有个副作用,就是会增大数据量,作为主键的列数据量会明显成倍增加。
melt
,融化。
melt()
函数原型
Pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)
frame
:要处理的dataframe
数据。id_vars
:tuple
/list
/ndarray
,用作标识变量的列,即不需要被转换的列名。value_vars
:tuple
/list
/ndarray
,即将被转换的列。 如果未指定,则使未被设置为id_vars
的所有列。var_name
:标量,用于“变量”列的名称。 如果未指定,则使用variable
。value_name
:标量,默认为value
,用于value
列的名称。col_level
:int
或str
,如果列是多重索引的,则使用此级别来融化。这个一般情况下用不到。ignore_index
:默认为True,也就是忽略原有的行名,从头开始计数行名。
原始数据
import pandas as pd
df = pd.DataFrame({
'name': ['虎子', '老许', '小黑'],
'foot': [10, 20, 30],
'height': [80, 30, 50]
},index=["a1","a2","a3"])
print(df)
输出:
name foot height
a1 虎子 10 80
a2 老许 20 30
a3 小黑 30 50
默认melt()效果
默认的转换效果,全部的列都被横过来了。新生成
df_melt = pd.melt(df)
print(df_melt)
输出:
variable value
0 name 虎子
1 name 老许
2 name 小黑
3 age 10
4 age 5
5 age 3
6 height 80
7 height 30
8 height 50
指定主键id_vars
df_melt = pd.melt(df, id_vars=['name'])
print(df_melt)
输出:
name variable value
0 虎子 age 10
1 老许 age 5
2 小黑 age 3
3 虎子 height 80
4 老许 height 30
5 小黑 height 50
df_melt = pd.melt(df, id_vars=['name','age'])
print(df_melt)
输出:
name age variable value
0 虎子 10 height 80
1 老许 5 height 30
2 小黑 3 height 50
修改新列名
df_melt = pd.melt(df, id_vars=['name'], var_name='new_column_name', value_name='new_column_value')
print(df_melt)
输出:
name new_column_name new_column_value
0 虎子 age 10
1 老许 age 5
2 小黑 age 3
3 虎子 height 80
4 老许 height 30
5 小黑 height 50
同时指定id_vars
和value_vars
df_melt = pd.melt(df, id_vars=['name'], value_vars=['age'])
print(df_melt)
输出:
name variable value
0 虎子 age 10
1 老许 age 5
2 小黑 age 3
值得说明的是:本操作故意丢失了height
数据。
ignore_index,忽略原有行名
不忽略的话,似乎很不妥当。
df_melt = pd.melt(df,ignore_index=False)
print(df_melt)
输出:
variable value
a1 name 虎子
a2 name 老许
a3 name 小黑
a1 foot 10
a2 foot 20
a3 foot 30
a1 height 80
a2 height 30
a3 height 50
多重索引col_index
多重索引的情况,目前还没有涉及过,这里仅仅放个例子,以后待议。
import pandas as pd
df = pd.DataFrame({'A': {0: '苏', 1: '南'},
'B': {0: "大", 1: "叔"},
'C': {0: 666, 1: 888}})
df.columns = pd.MultiIndex.from_arrays([list('ABC'), list('DEF')], names=list('ab'))
print (df)
print (df.melt(col_level='b'))
输出:
a A B C
b D E F
0 苏 大 666
1 南 叔 888
b value
0 D 苏
1 D 南
2 E 大
3 E 叔
4 F 666
5 F 888
melt()
对比.T
操作
melt()
作用是宽表变长表,而.T
作用是行列互换。
区分 | 主体.size | 旧列名 | 旧行名 |
---|---|---|---|
melt() | id_vars的数据重复增加 | 旧的变成数据,新列名可指定 | 默认重置,也可以随数据增多而增多 |
.T | 不变 | 变成行名 | 变成列名 |
melt()
之后可能需要的操作
melt()
之后,肉眼可见的标签(行名列名)大混乱。所以,您可能需要下面的操作:
df.columns = ["col1","col2","col3"]
或者:
df.index= ["row1","row2"]
或者:
df.rename(
columns={"name": "姓名", "age": "年龄", "label": "标签", "无关": "瞎写"},
index={"a1": "第一行", "a2": "第二行"},
inplace=True,
)
参考文章:
结束语
这个melt
可以丢失数据(指定value_vars
),默认增多数据,行名索引也会默认被重置。总之,不是很好用。列转行的操作,仅仅是把部分列数据变成了行,和期待的行列数据互换还有较大差距。
如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。