merge、concat、join三张表合并搞崩你的不是语法是逻辑数据分析里很少只用一张表。订单表、用户表、商品表——三张拼一起才能出洞察。但表合并是 Pandas 新手最容易写错的地方。今天把 concat、merge、join 的区别一次说清。concat简单粗暴的拼接concat 就像在 Excel 里把两张表头一样的表上下贴在一起。importpandasaspd df1pd.DataFrame({A:[1,2],B:[3,4]})df2pd.DataFrame({A:[5,6],B:[7,8]})# 纵向拼接默认resultpd.concat([df1,df2],ignore_indexTrue)print(result)# A B# 0 1 3# 1 2 4# 2 5 7# 3 6 8# 横向拼接resultpd.concat([df1,df2],axis1)print(result)列不一样怎么办df1pd.DataFrame({A:[1,2],B:[3,4]})df2pd.DataFrame({B:[5,6],C:[7,8]})# joinouter取并集缺的地方填 NaNresultpd.concat([df1,df2],joinouter)# A B C# 0 1.0 3 NaN# 1 2.0 4 NaN# 0 NaN 5 7.0# 1 NaN 6 8.0# joininner取交集只保留共有的列resultpd.concat([df1,df2],joininner)# B# 0 3# 1 4# 0 5# 1 6merge像 SQL 的 JOIN# 用户表userspd.DataFrame({user_id:[1,2,3,4],name:[张三,李四,王五,赵六],city:[北京,上海,广州,深圳]})# 订单表orderspd.DataFrame({order_id:[101,102,103,104,105],user_id:[1,2,2,3,5],# 注意user_id5 不在用户表里amount:[150,200,300,100,500]})四种连接方式# inner只保留两边都有的交集resultpd.merge(users,orders,onuser_id,howinner)print(finner:{len(result)}行)# 4行user_id5被排除# left保留左边全部右边没有的填 NaNresultpd.merge(users,orders,onuser_id,howleft)print(fleft:{len(result)}行)# 5行赵六没有订单# right保留右边全部resultpd.merge(users,orders,onuser_id,howright)print(fright:{len(result)}行)# 5行user_id5的用户信息是NaN# outer两边都保留resultpd.merge(users,orders,onuser_id,howouter)print(fouter:{len(result)}行)# 6行怎么选记住这个需求用“所有用户和他们的订单”用户必须有leftusers 在左“有订单的用户信息”inner“所有用户和所有订单全都要”outer列名不一样时userspd.DataFrame({uid:[1,2,3],name:[张三,李四,王五]})orderspd.DataFrame({user_id:[1,2,2],amount:[150,200,300]})# left_on 和 right_on 分别指定resultpd.merge(users,orders,left_onuid,right_onuser_id)print(result)# 合并后删掉重复列result.drop(columns[user_id],inplaceTrue)join按索引合并df1pd.DataFrame({A:[1,2,3]},index[a,b,c])df2pd.DataFrame({B:[4,5]},index[a,c])# join 按索引合并默认 leftresultdf1.join(df2,howleft)print(result)# A B# a 1 4.0# b 2 NaN# c 3 5.0merge 也可以按索引pd.merge(df1, df2, left_indexTrue, right_indexTrue)。合并后数据验证防丢数据# 合并前后行数检查print(fusers:{len(users)}, orders:{len(orders)})resultpd.merge(users,orders,onuser_id,howleft)print(f合并后:{len(result)})# 检查有没有丢数据lost_usersset(users[user_id])-set(result[user_id])iflost_users:print(f丢失的用户ID:{lost_users})# 检查重复ifresult.duplicated(subset[user_id]).any():print(警告有重复的 user_id)实战订单用户商品三表联查# 三张表userspd.DataFrame({user_id:[1,2,3],name:[张三,李四,王五],level:[VIP,普通,VIP]})productspd.DataFrame({product_id:[101,102,103],product_name:[手机,电脑,耳机],category:[电子,电子,配件]})orderspd.DataFrame({order_id:[1001,1002,1003,1004,1005],user_id:[1,1,2,3,2],product_id:[101,102,101,103,102],quantity:[1,1,2,5,1],price:[2999,5999,2999,199,5999]})# 三表合并fullorders.merge(users,onuser_id)\.merge(products,onproduct_id)print( 完整订单明细 )print(full.head())# 分析各等级用户消费print(\n 各等级消费总额 )print(full.groupby(level)[price].sum())# 分析各品类销量print(\n 各品类销量 )print(full.groupby(category)[quantity].sum())# 各用户最常买的品类print(\n 用户偏好 )preffull.groupby([name,category])[quantity].sum()print(pref)新手常见坑坑1合并后行数变多# 右表有重复的关联键 → 行数膨胀# 比如一个用户有3条订单合并后这个用户出现3次# 这是正常的但要注意检查print(f合并前行数{len(df1)}{len(df2)}{len(df1)len(df2)})print(f合并后行数{len(result)})坑2关联键类型不一致# df1 的 id 是 intdf2 的 id 是 str → 合并不上df1[id]df1[id].astype(str)# 或者df2[id]df2[id].astype(int)坑3concat 时列顺序不对# 列名对不上会创建新列# 先统一列名df2.columnsdf1.columns resultpd.concat([df1,df2])动手试试创建两张表用 merge 做 inner join 并检查结果把三个 CSV 文件用 concat 拼成一个做一个三表联查的分析输出汇总结果写在最后表合并是数据分析的基本功。三点建议合并前print(len(df))确认行数合并后检查有没有丢数据搞清楚 inner/left/right/outer 的区别别瞎试下一篇开始画图——Matplotlib 入门。