Courses
宽格式数据便于阅读,但许多分析和可视化任务在长格式下效果更佳。
pandas.melt() 函数通过将一个或多个列转为行、同时保留选定的标识符列不变,来重塑 DataFrame。这使您的数据更易于筛选、分组、可视化与分析。
在本教程中,我将向您演示如何使用 pandas.melt() 函数,并比较它与 pivot()、stack() 和 wide_to_long() 等选项的差异。如果您刚开始学习 Python,我建议您参加 our Introduction to Python course,该课程涵盖数据类型、列表、基础函数和包等技能。
如何使用 pandas.melt()
pandas.melt() 通过将列名转换为新列中的取值,把 DataFrame 从宽格式转换为长格式。
其语法如下:
pandas.melt(
frame,
id_vars=None,
value_vars=None,
var_name=None,
value_name="value",
col_level=None,
ignore_index=True
)
其中:
-
frame:要重塑的 DataFrame。仅在使用pandas.melt()时必填。 -
id_vars:需要保持不变的列或列列表。这些列在重塑后用于标识每一行。 -
value_vars:要“反透视”(unpivot)的列或列列表。如果省略,pandas 会熔化所有不在id_vars中的列。 -
var_name:存储原始列名的新列名称。若未指定,默认为“variable”。 -
value_name:存储数值的新列名称。若未指定,默认为“value”。 -
col_level:可选,在处理多级列索引(MultiIndex)时指定要熔化的层级。 -
ignore_index:若为True(默认),创建新的顺序索引;若为False,保留原始索引。
下面通过一个示例演示上述语法如何重塑数据。
假设您有如下数据集,每个产品的月度销量分别存放在不同的列中。

您可以使用 pandas.melt() 将月份列转换为行。
# Convert the DataFrame from wide format to long format
products_sales_2025_melted = products_sales_2025.melt(
# Keep the Product and Category columns unchanged
id_vars=["Product", "Category"],
# Convert the month columns into rows
value_vars=["January", "February", "March", "April", "May", "June"],
# Name of the new column that stores the original column names
var_name="Month",
# Name of the new column that stores the corresponding sales values
value_name="Sales"
)
# Display the reshaped DataFrame
products_sales_2025_melted.head(10)
得到的 DataFrame 现在将每个月份作为单独的行存储。

常见的 pandas.melt() 示例
既然您已经理解了 pandas.melt() 的语法,下面展示各参数单独使用时的行为。接下来的示例将使用上面的表格。
仅熔化选定列
value_vars 参数可指定要反透视的列。您可以只转换需要的列,而不是熔化每一个月份。
在此示例中,仅熔化了一月和二月列。其余月份列将被忽略。
# Convert only the January and February columns into rows
product_sales_3month = products_sales_2025.melt(
id_vars="Product",
value_vars=["January", "February",]
)
product_sales_3month.head(20)

保留标识符列
使用 id_vars 参数可在重塑其他列的同时,保留一个或多个列不变。
在下面的示例中,“Product”和“Category”保持不变,而月度销量列被转换为行。
# Keep the Product and Category columns while melting the monthly sales
product_sales_cat = products_sales_2025.melt(
id_vars=["Product", "Category"]
)
product_sales_cat.head()

重命名输出列
您会注意到,输出列默认命名为 variable 和 value。使用 var_name 和 value_name 参数为它们赋予更具描述性的名称。
例如,在下面的输出中,我们将变量列重命名为“Month”,将数值列重命名为“Sales”。
# Keep the Product and Category columns while melting the monthly sales
# Rename Month and Sales columns
product_sales_cat = products_sales_2025.melt(
id_vars=["Product", "Category"],
var_name="Month",
value_name="Sales"
)
product_sales_cat.head()

保留原始索引
默认情况下,pandas.melt() 会创建新的顺序索引。将 ignore_index=False 设置为保留原始行索引。
# Keep the original row index after reshaping
product_sales_index = products_sales_2025.melt(
id_vars=["Product", "Category"],
var_name="Month",
value_name="Sales",
ignore_index=False
)
product_sales_index.head(10)

在上面的示例中,原始行标签(0–5)会在每个月份重复,而不是被新的顺序索引替换。
何时应该使用 pandas.melt()?
pandas.melt() 适用于当数据为宽格式、需要转换为长格式以便分析或可视化的场景。我也常在以下用例中使用该函数:
-
将宽格式数据转换为长格式:许多数据集把相关数值分散在多个列中。虽然这种格式易读,但会增加分析难度。
pandas.melt()能将这些列合并为单一列,同时保留标识符列,从而为后续处理创建更清晰的结构。 -
为绘图做准备:许多绘图库(如 Seaborn)在创建图表时更偏好长格式数据。与其手动合并多列,不如使用
pandas.melt()将数据重塑为这些库期望的格式。 -
为统计分析做准备:当测量值集中在单一列而非分散在多列时,许多 pandas 操作(包括
groupby()、聚合、筛选和汇总统计)会更简单。使用pandas.melt()重塑数据,可减少针对不同变量编写的代码量。 -
创建整洁数据集:整洁数据集要求每个变量存放在自己的列、每条观测占据自己的行。如果您的数据集中在多个列中包含重复测量,
pandas.melt()往往是将其转换为整洁格式的最快方式。
我建议您参加我们的 Introduction to Data Visualization with Seaborn 课程,学习如何在 Python 中创建并自定义多种图表,包括散点图、计数图、柱状图和箱线图。
pandas.melt() 与其他重塑函数的比较
Pandas 提供了多种数据重塑函数,各有用途。下面来比较它们之间的差异。
pandas.melt() vs. pivot()
下表展示了 pandas.melt() 与 pivot() 函数的区别。
|
|
|
|
将宽数据转换为长数据。 |
将长数据转换为宽数据。 |
|
将列转换为行。 |
将行中的取值转换为列。 |
|
有助于为分析与可视化做准备。 |
有助于在报告中汇总或呈现数据。 |
因此,当测量值分散在多个列中时选择 melt();当您希望将行中的取值展开到各列时使用 pivot()。
pandas.melt() vs. stack()
虽然二者都能重塑数据,但它们的差异如下。
|
|
|
|
将常规列重塑为行。 |
将一个或多个列层级移入索引。 |
|
生成标准的 DataFrame。 |
生成带有多级索引(MultiIndex)的 Series 或 DataFrame。 |
|
对大多数分析任务而言更易读、易用。 |
更适合基于索引的重塑操作。 |
您 can 在需要处理分层索引或 MultiIndex 对象时使用 stack()。
pandas.melt() vs. wide_to_long()
两者都将宽数据转换为长格式,but 它们面向的情形不同,如下所示。
|
|
|
|
灵活,几乎适用于任何 DataFrame。 |
为具有一致列命名模式的数据集而设计。 |
|
适合通用重塑。 |
适用于重复测量,如 Sales_2023、Sales_2024 和 Sales_2025。 |
如果您的数据集列名不规则,请使用 melt()。如果列遵循可预测的命名规范,请使用 wide_to_long() 以更少的代码完成重塑。
使用 pandas.melt() 的常见错误
尽管 pandas.melt() 使用起来相对直接,但我遇到过以下常见陷阱,以及对应的修正方法。
-
忘记设置 id_vars:如果您未指定
id_vars,pandas 会将未列入value_vars的所有列视为数值列。这可能会把您原本想保留为标识符的列重塑掉。要修正这一点,请始终识别能唯一描述每条记录的列,并将它们传入id_vars。 -
意外熔化了不该处理的列:如果省略
value_vars,pandas 会熔化所有未包含在id_vars中的列,这可能包含您并不打算重塑的列。因此,当您只想熔化部分列时,应始终显式指定value_vars。 -
误解输出形状:熔化后,行数会增加,因为每个被选中的列会为每条记录生成一行。例如,一个有 10 行和 12 个月份列的 DataFrame,在熔化月份列后会产生 120 行。因此,请始终在重塑前后检查数据形状,确认熔化是否符合预期。
-
混淆宽格式与长格式:务必记住,宽格式中,相似的取值分布在多个列中;而在长格式中,相似的取值集中在单一列中,另有一列用于标识变量。
使用 pandas.melt() 的最佳实践
为了让您的重塑代码更易理解与维护,使用 pandas.melt() 时我建议遵循以下最佳实践:
-
先识别标识符列:确定哪些列应保持不变,然后将它们传入
id_vars。 -
重命名生成的列:使用
var_name与value_name,而非依赖默认的 variable 与 value 列名。 -
在熔化后检查行数:尤其在熔化多列时,验证行数是否符合预期。
-
需要还原时使用 pivot():分析结束后若需恢复到原始宽格式,使用
pivot()函数。
参加 our Writing Efficient Python Code 课程,了解如何编写高效、易调试与易维护的代码。
结语
pandas.melt() 是将宽格式数据转换为长格式数据的标准 pandas 函数。一旦理解了 id_vars 与 value_vars 的作用,您就可以控制哪些列作为标识符保留、哪些列转换为行。
若想系统学习 Python,您可以进一步学习我们的 Python Data Fundamentals 和 Python Programming Fundamentals 技能路径。
FAQs
我应该何时使用 pandas.melt()?
当您的数据将重复的取值分散在多个列中,而您希望获得用于分析或可视化的长格式 DataFrame 时使用它。
什么是 var_name 和 value_name?
这些参数用于重命名生成的列,分别存放原始列名及其对应的数值。
pandas.melt() 会修改原始 DataFrame 吗?
不会。它会返回一个新的重塑后的 DataFrame,原始数据保持不变。
melt() 与 pivot() 有何区别?
melt() 将宽格式数据转换为长格式,而 pivot() 则将长格式数据转换回宽格式。
melt() 与 stack() 有何区别?
melt() 在保留常规 DataFrame 的同时将列重塑为行;stack() 则将列移入索引,创建分层(MultiIndex)结构。