如何用Pandas实现多表合并,达到类数据库Join效果
如何用Pandas实现多表Join得到完整数据集?
问题描述
需要合并3个数据表(两个业务信息表+一个中间关联表),最终得到包含userId, bookId, likes, title, author, Location, Age的数据集,实现类似SQL的Join效果。
相关列定义:
import pandas as pd r_names = ['userId', 'bookId', 'likes'] cols1 = ['userId', 'bookId', 'likes'] u_names = ['userId', 'Location', 'Age'] cols2 = ['userId', 'Location', 'Age'] b_names = ['bookId','title', 'author'] cols3 = ['bookId','title', 'author']
读取文件代码:
df1 = pd.read_csv('Ratings.csv', header=None, encoding="ISO-8859-1", names=r_names, usecols=cols1, index_col='userId') df2 = pd.read_csv('Users.csv', header=None, encoding="ISO-8859-1", names=u_names, usecols=cols2, index_col='userId') df3 = pd.read_csv('Books.csv', header=None, encoding="ISO-8859-1", names=b_names, usecols=cols3, index_col='bookId')
当前合并代码导致信息不完整:
df4 = pd.merge(df1, df2, how='outer', on=['userId']) df5 = pd.merge(df3, df4, how='outer', on=['bookId']) df5.to_csv('dataset', sep='\t', encoding='utf-8') result = df5.head(10) print("First 10 rows of the DataFrame:") print(result)
问题原因
当前合并失败的核心问题是:读取文件时设置了index_col,导致关联键(userId/bookId)成为DataFrame的索引,而pd.merge默认仅使用普通列进行关联,不会自动识别索引列。此外,outer join会保留所有表的所有行,可能引入大量空值,若业务不需要全量数据,会造成"信息不完整"的错觉。
正确实现方案
方案1:读取时不设置索引,用普通列关联(推荐)
这是最直观的方式,让关联键作为普通列存在,避免索引带来的关联问题:
import pandas as pd # 读取文件时不指定index_col,关联键保留为普通列 df1 = pd.read_csv('Ratings.csv', header=None, encoding="ISO-8859-1", names=r_names, usecols=cols1) df2 = pd.read_csv('Users.csv', header=None, encoding="ISO-8859-1", names=u_names, usecols=cols2) df3 = pd.read_csv('Books.csv', header=None, encoding="ISO-8859-1", names=b_names, usecols=cols3) # 分步合并:先关联用户表与评分表(userId),再关联书籍表(bookId) # 根据业务需求选择join类型:inner保留有效关联数据,outer保留全量数据 merged_df = pd.merge(df1, df2, on='userId', how='inner') merged_df = pd.merge(merged_df, df3, on='bookId', how='inner') # 调整列顺序为预期格式 desired_cols = ['userId', 'bookId', 'likes', 'title', 'author', 'Location', 'Age'] merged_df = merged_df[desired_cols] # 输出结果 merged_df.to_csv('dataset.tsv', sep='\t', encoding='utf-8', index=False) print("First 10 rows of merged DataFrame:") print(merged_df.head(10))
方案2:保留索引时显式指定索引关联
若因其他需求必须设置index_col,可在合并时明确指定使用索引进行关联:
import pandas as pd # 保留索引的读取方式 df1 = pd.read_csv('Ratings.csv', header=None, encoding="ISO-8859-1", names=r_names, usecols=cols1, index_col='userId') df2 = pd.read_csv('Users.csv', header=None, encoding="ISO-8859-1", names=u_names, usecols=cols2, index_col='userId') df3 = pd.read_csv('Books.csv', header=None, encoding="ISO-8859-1", names=b_names, usecols=cols3, index_col='bookId') # 合并用户表与评分表:使用双方的userId索引 user_rating_merge = pd.merge(df1, df2, left_index=True, right_index=True, how='inner') # 重置索引将userId转回普通列,再与书籍表的bookId索引关联 merged_df = pd.merge(user_rating_merge.reset_index(), df3.reset_index(), on='bookId', how='inner') # 调整列顺序 desired_cols = ['userId', 'bookId', 'likes', 'title', 'author', 'Location', 'Age'] merged_df = merged_df[desired_cols] # 输出结果 merged_df.to_csv('dataset.tsv', sep='\t', encoding='utf-8', index=False) print(merged_df.head(10))
关键注意事项
- 关联键的存在形式:
pd.merge默认仅识别普通列,若关联键是索引,需显式设置left_index=True或right_index=True。 - Join类型选择:
how='inner':仅保留三个表中存在有效关联的行,无冗余空值,适合多数业务场景。how='outer':保留所有表的所有行,会引入大量空值,仅在需要全量数据时使用。
- 列顺序控制:通过指定列列表可确保输出数据集的列顺序完全符合预期。
内容的提问来源于stack exchange,提问作者snloD
相关产品推荐
相关产品推荐

