第七章:DataFrame 的合并、连接与重塑
7.1 合并 DataFrame(merge方法)
在数据分析中,经常需要将多个 DataFrame 合并成一个,merge 方法是实现这一操作的常用工具。它基于一个或多个共同的列或索引来连接 DataFrame。
7.1.1 基于单个列合并
假设有两个 DataFrame,一个包含学生的基本信息,另一个包含学生的成绩信息,它们都有 '学号' 列,我们可以基于 '学号' 列将两个 DataFrame 合并。
import pandas as pd
students_info = pd.DataFrame({
'学号': [1, 2, 3],
'姓名': ['Alice', 'Bob', 'Charlie']
})
students_scores = pd.DataFrame({
'学号': [1, 2, 4],
'成绩': [85, 90, 78]
})
merged_df = pd.merge(students_info, students_scores, on='学号')
print(merged_df)
在上述代码中,pd.merge(students_info, students_scores, on='学号') 基于 '学号' 列将 students_info 和 students_scores 合并。输出结果为:
学号 姓名 成绩
0 1 Alice 85
1 2 Bob 90
可以看到,只有学号相同的行被合并,并且 students_scores 中 学号 为 4 的行由于在 students_info 中没有匹配项,未出现在结果中。
7.1.2 基于多个列合并
如果两个 DataFrame 有多列可以作为连接键,我们可以传递列名列表给 on 参数。
import pandas as pd
df1 = pd.DataFrame({
'学号': [1, 2, 3],
'班级': ['A', 'B', 'A'],
'姓名': ['Alice', 'Bob', 'Charlie']
})
df2 = pd.DataFrame({
'学号': [1, 2, 3],
'班级': ['A', 'B', 'A'],
'成绩': [85, 90, 78]
})
merged_df = pd.merge(df1, df2, on=['学号', '班级'])
print(merged_df)
这里 pd.merge(df1, df2, on=['学号', '班级']) 基于 '学号' 和 '班级' 两列进行合并,输出为:
学号 班级 姓名 成绩
0 1 A Alice 85
1 2 B Bob 90
2 3 A Charlie 78
只有 学号 和 班级 都相同的行才会被合并。
7.1.3 不同连接方式(how参数)
merge 方法的 how 参数可以指定连接方式,常见的有 'inner'(内连接,默认值)、'outer'(外连接)、'left'(左连接)和 'right'(右连接)。
- 外连接(how='outer'):
import pandas as pd
students_info = pd.DataFrame({
'学号': [1, 2, 3],
'姓名': ['Alice', 'Bob', 'Charlie']
})
students_scores = pd.DataFrame({
'学号': [1, 2, 4],
'成绩': [85, 90, 78]
})
merged_df = pd.merge(students_info, students_scores, on='学号', how='outer')
print(merged_df)
外连接会保留两个 DataFrame 中所有的行,对于没有匹配的行,相应列会填充 NaN。输出为:
学号 姓名 成绩
0 1 Alice 85.0
1 2 Bob 90.0
2 3 Charlie NaN
3 4 NaN 78.0
- 左连接(how='left'):
import pandas as pd
students_info = pd.DataFrame({
'学号': [1, 2, 3],
'姓名': ['Alice', 'Bob', 'Charlie']
})
students_scores = pd.DataFrame({
'学号': [1, 2, 4],
'成绩': [85, 90, 78]
})
merged_df = pd.merge(students_info, students_scores, on='学号', how='left')
print(merged_df)
左连接以左 DataFrame(students_info) 为基准,保留左 DataFrame 的所有行,对于在右 DataFrame 中没有匹配的行,相应列填充 NaN。输出为:
学号 姓名 成绩
0 1 Alice 85.0
1 2 Bob 90.0
2 3 Charlie NaN
- 右连接(how='right'):
import pandas as pd
students_info = pd.DataFrame({
'学号': [1, 2, 3],
'姓名': ['Alice', 'Bob', 'Charlie']
})
students_scores = pd.DataFrame({
'学号': [1, 2, 4],
'成绩': [85, 90, 78]
})
merged_df = pd.merge(students_info, students_scores, on='学号', how='right')
print(merged_df)
右连接以右 DataFrame(students_scores) 为基准,保留右 DataFrame 的所有行,对于在左 DataFrame 中没有匹配的行,相应列填充 NaN。输出为:
学号 姓名 成绩
0 1 Alice 85.0
1 2 Bob 90.0
2 4 NaN 78.0
7.2 连接 DataFrame(concat方法)
concat 方法用于沿指定轴连接 DataFrame,它不会像 merge 那样基于共同列或索引进行连接,而是简单地将 DataFrame 拼接在一起。
7.2.1 按行连接(axis = 0)
import pandas as pd
df1 = pd.DataFrame({
'A': [1, 2],
'B': [3, 4]
})
df2 = pd.DataFrame({
'A': [5, 6],
'B': [7, 8]
})
concatenated_df = pd.concat([df1, df2], axis = 0)
print(concatenated_df)
上述代码中,pd.concat([df1, df2], axis = 0) 将 df1 和 df2 按行连接,axis = 0 表示沿行方向拼接。输出为:
A B
0 1 3
1 2 4
0 5 7
1 6 8
可以看到,df2 直接接在了 df1 的下方,索引也保留了原 DataFrame 的索引,如果需要重新索引,可以使用 ignore_index = True 参数。
7.2.2 按列连接(axis = 1)
import pandas as pd
df1 = pd.DataFrame({
'A': [1, 2],
'B': [3, 4]
})
df2 = pd.DataFrame({
'C': [5, 6],
'D': [7, 8]
})
concatenated_df = pd.concat([df1, df2], axis = 1)
print(concatenated_df)
这里 pd.concat([df1, df2], axis = 1) 按列连接 df1 和 df2,axis = 1 表示沿列方向拼接。输出为:
A B C D
0 1 3 5 7
1 2 4 6 8
df2 的列接在了 df1 的右侧。
7.3 重塑 DataFrame
重塑操作可以改变 DataFrame 的形状和结构,常见的重塑操作有 pivot 和 melt。
7.3.1 pivot操作
pivot 方法用于将长格式数据转换为宽格式数据。例如,有一份销售数据,包含产品名称、销售月份和销售额,我们想将其转换为以产品名称为行,销售月份为列,销售额为值的表格。
import pandas as pd
data = {
'产品名称': ['苹果', '苹果', '香蕉', '香蕉'],
'销售月份': ['一月', '二月', '一月', '二月'],
'销售额': [100, 120, 150, 130]
}
df = pd.DataFrame(data)
pivoted_df = df.pivot(index='产品名称', columns='销售月份', values='销售额')
print(pivoted_df)
pivot 方法中,index 指定行索引,columns 指定列索引,values 指定填充表格的值。输出为:
销售月份 一月 二月
产品名称
苹果 100 120
香蕉 150 130
7.3.2 melt操作
melt 操作与 pivot 相反,它将宽格式数据转换为长格式数据。假设我们有一个宽格式的销售数据 DataFrame,想将其转换为长格式。
import pandas as pd
data = {
'产品名称': ['苹果', '香蕉'],
'一月': [100, 150],
'二月': [120, 130]
}
df = pd.DataFrame(data)
melted_df = pd.melt(df, id_vars=['产品名称'], var_name='销售月份', value_name='销售额')
print(melted_df)
id_vars 指定保留的列,var_name 为新的变量名(原列名),value_name 为新的值名。输出为:
产品名称 销售月份 销售额
0 苹果 一月 100
1 香蕉 一月 150
2 苹果 二月 120
3 香蕉 二月 130
通过这些合并、连接与重塑操作,可以灵活地处理和整理数据,以满足不同的数据分析需求。