df长宽变形大师 - melt的重塑神功

pandas重塑函数-melt的介绍与练习

Posted by Hilda on February 28, 2025

NumPy 博客总结:

《Python数据分析基础教程:NumPy学习指南(第2版)》所有章节阅读笔记+代码

70道NumPy 面试题(题目+答案)

pandas博客总结:

pandas(1)数据预处理

pandas(2)数据分析

pandas(3)常用函数操作

pandas(4)大数据处理技巧

【力扣】pandas入门15题

返回与输入组具有相同形状的结果的transform函数


本篇提供几道关于 Pandas melt() 函数的练习题,包含答案和详细解析,但是首先记录下怎么学习这个函数。

理解 melt 的核心概念

  • 作用:把 DataFrame 从“宽表”(列多)变成“长表”(行多)。
  • 比喻:想象你在融化一个表格,把列“融化”成行,像把一块方形巧克力融化成一条条液体。
  • 输入和输出:
    • 输入:一个宽格式的 DataFrame(比如每列是一个变量)。
    • 输出:一个长格式的 DataFrame(变量名和值分别在两列中)。

核心参数(必须记住的)

函数签名:

1
pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)

id_vars:不“融化”的列,保持不变,作为标识列(比如 ID、姓名)。

  • 记忆:想成“identity variables”(标识变量)。

value_vars:要“融化”的列,如果不指定,默认融化除 id_vars 外的所有列。

  • 记忆:想成“value variables”(值变量)。

var_name:融化后变量名的列名,默认是“variable”。

  • 记忆:这是“变量的名字”。

value_name:融化后的列名,默认是“value”。

  • 记忆:这是“值的内容”。

假设有

   name  math  english
0  Alice   90      85
1  Bob     80      95

使用melt:

1
pd.melt(df, id_vars=['name'], value_vars=['math', 'english'], var_name='subject', value_name='score')

最终结果:

    name  subject  score
0  Alice     math     90
1    Bob     math     80
2  Alice  english     85
3    Bob  english     95

次要参数(用时再查)

这些参数不常用,理解即可:

  • col_level:多层索引时指定操作哪一层,通常用不到。
  • ignore_index(pandas 1.1.0+):是否重置索引,默认 True。

习题

1.电影评分数据

已有数据:

1
2
3
4
{'user_id': [1, 2, 3, 4, 5],
        'movie_A': [4, 5, None, 2, 3],
        'movie_B': [5, None, 3, 4, 1],
        'movie_C': [None, 4, 2, 5, None]}

要求:

  1. 使用 melt() 函数将 DataFrame 转换为长格式,其中包含 user_idmovie_titlerating 三列。
  2. 删除 rating 列中的缺失值(NaN)。

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
data = {'user_id': [1, 2, 3, 4, 5],
        'movie_A': [4, 5, None, 2, 3],
        'movie_B': [5, None, 3, 4, 1],
        'movie_C': [None, 4, 2, 5, None]}
movie = pd.DataFrame(data)
display(movie)

# 应用melt函数,包含` user_id`、`movie_title` 和 `rating` 三列
movie_melt = movie.melt(id_vars=['user_id'], value_vars=['movie_A', 'movie_B', 'movie_C'], var_name='movie_title', value_name='rating')

# 去掉缺失值
movie_melt = movie_melt.dropna(subset=['rating'])
display(movie_melt)

image-20250228155039814

2.学生考试成绩

记录学生在不同科目中的考试成绩, 结构如下:

1
2
3
4
{'student_id': [101, 102, 103],
        'math_score': [85, 92, 78],
        'english_score': [90, 88, 95],
        'science_score': [75, 80, 82]}

要求:

  1. 使用 melt() 函数将 DataFrame 转换为长格式,其中包含 student_id、subject 和 score 三列。
  2. 创建一个新的 DataFrame,计算每个科目的平均分数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
data = {'student_id': [101, 102, 103],
        'math_score': [85, 92, 78],
        'english_score': [90, 88, 95],
        'science_score': [75, 80, 82]}

students = pd.DataFrame(data)
display(students)
students = students.rename(
    columns={
        'math_score':'math',
        'english_score':'english',
        'science_score':'science'
    }
)
# 包含 student_id、subject 和 score 三列,计算每个科目的平均分数。
students_melt = students.melt(id_vars=['student_id'], value_vars=['math', 'english', 'science'], var_name='subject', value_name='score')

display(students_melt)

# 用groupby
mean_every_subject = pd.DataFrame(students_melt.groupby('subject')['score'].mean())

display(mean_every_subject)

image-20250228160409580

3.销售数据 (多个指标)

记录不同产品的销售数据,包括销售额和成本。 结构如下:

1
2
3
4
5
{'product_id': [1, 2, 3],
        'sales_Q1': [1000, 1500, 1200],
        'cost_Q1': [500, 750, 600],
        'sales_Q2': [1200, 1800, 1400],
        'cost_Q2': [600, 900, 700]}

要求:

  1. 使用 melt() 函数将 DataFrame 转换为长格式,其中包含 product_id、quarter 和 value 三列。 quarter 列应包含类似 “sales_Q1” 这样的值。
  2. 添加一个新列 metric,用于区分 ‘sales’ 和 ‘cost’。提示:可以使用字符串操作。
  3. 创建一个新的 DataFrame,计算每个季度每个指标的总值。

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
data = {'product_id': [1, 2, 3],
        'sales_Q1': [1000, 1500, 1200],
        'cost_Q1': [500, 750, 600],
        'sales_Q2': [1200, 1800, 1400],
        'cost_Q2': [600, 900, 700]}

products = pd.DataFrame(data)
display(products)

# 包含 product_id、quarter 和 value 三列。 quarter 列应包含类似 "sales_Q1" 这样的值。
products = products.melt(id_vars=['product_id'], value_vars=['sales_Q1', 'sales_Q2', 'cost_Q1', 'cost_Q2'], var_name='quarter', value_name='value')
display(products)
# 添加一个新列 metric,用于区分 'sales' 和 'cost'。提示:可以使用字符串操作。
products['metric'] =  products['quarter'].str.split('_').str[0]
display(products)

# 创建一个新的 DataFrame,计算每个季度每个指标的总值。(很明显要操作最新的products)
display(pd.DataFrame(products.groupby(['quarter', 'metric'])['value'].sum()))

最后打印的2个df:

image-20250228161754670

这些练习题涵盖了 melt() 函数的常见用例,包括处理缺失值、计算统计量和处理多个指标。 通过完成这些练习,你应该能够熟练地使用 melt() 函数来转换和重塑 Pandas DataFrame。 掌握字符串操作也是解决复杂数据处理问题的关键。