我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

pandas里面有一个melt()方法,操作对象是dataframe。可以把一部分列数据变成横向的行数据。这个列变成行的效果,转换的也并不完全。这个函数的主要功能是把部分列数据变成行数据,也有部分列数据保持不变。同时也会有数据增生的现象发生,原列标签会变成主体内容,同时生成新的列标签。总之,就是和行列互换的需求是完全不同的结果。

苏南大叔:如何利用pandas的melt()方法,实现宽表转长表的操作? - pandas-melt
如何利用pandas的melt()方法,实现宽表转长表的操作?(图3-1)

大家好,这里是苏南大叔的"程序如此灵动"博客,本文记录pandasmelt()方法。测试环境:win10python@3.11.0numpy@1.24.2pandas@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_varstuple/list/ndarray,用作标识变量的列,即不需要被转换的列名。
  • value_varstuple/list/ndarray,即将被转换的列。 如果未指定,则使未被设置为id_vars的所有列。
  • var_name:标量,用于“变量”列的名称。 如果未指定,则使用variable
  • value_name:标量,默认为value,用于value列的名称。
  • col_levelintstr,如果列是多重索引的,则使用此级别来融化。这个一般情况下用不到。
  • 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

苏南大叔:如何利用pandas的melt()方法,实现宽表转长表的操作? - melt效果
如何利用pandas的melt()方法,实现宽表转长表的操作?(图3-2)

指定主键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

苏南大叔:如何利用pandas的melt()方法,实现宽表转长表的操作? - melt效果2
如何利用pandas的melt()方法,实现宽表转长表的操作?(图3-3)

同时指定id_varsvalue_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),默认增多数据,行名索引也会默认被重置。总之,不是很好用。列转行的操作,仅仅是把部分列数据变成了行,和期待的行列数据互换还有较大差距。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   python