Python进行数据拆分和合并的超详细指南 前言拆分和合并这两个词在数据处理的语境里其实很含糊。标题把它们并列 容易让人以为只有一种操作——实际在 pandas 里这两个方向各自都至少有三类含义拆分把一列字符串拆成多列、把一张表按某个键拆成若干张子表、把一格里的列表拆成多行合并纵向堆叠concat、横向按键对齐merge、按索引拼接join、缺失值互补combine_first。如果分不清是哪一类就会写出用split却想拆行这种对不上的代码。 本文按这几种真实场景逐一说清并给出可直接照着推演的示例。再次提醒pandas 是第三方库本机没有安装、也没有 Python 解释器 示例无法运行验证只能逐行人工推演。具体参数以 Pandas 官方文档为准。一、拆分之一把字符串列拆成多列Series.str.split是向量化的字符串切分配合expandTrue直接得到多列。# pandas 1.0import pandas as pddf pd.DataFrame({full: [Alice,25,Beijing, Bob,30,Shanghai]})parts df[full].str.split(,, expandTrue)parts.columns [name, age, city]print(parts)关键点expandTrue才返回DataFrame默认False返回每格一个列表的Series。拆出来的列是object类型数字列要再astype(int)转换。元素个数不一致时短的那侧会补NaN要留意。注意str.split与 Python 内置的str.split语义相近但pandas版本多了一个expand/n的开关。内置str.split(sepNone, maxsplit-1)保持原样。二、拆分之二把一格列表拆成多行如果某一列的每个单元格本身就是列表要把它炸开成多行用explode。# DataFrame.explode 需要 pandas 0.25ignore_index 参数需要 pandas 1.1df pd.DataFrame({order: [A, B], items: [[apple, pear], [banana]]})long df.explode(items, ignore_indexTrue)print(long)explode(column, ignore_indexFalse)会把 list-like 的每个元素变成一行 并复制同一行的其他列值。它是官方 API不是自己写的循环。若列表为空 结果里会保留一行NaN这一点常被忽略。三、拆分之三按分组键拆成多张子表groupby之后可以迭代每个分组是一个(键, 子 DataFrame)对# pandas 1.0groups {city: sub for city, sub in df.groupby(city)}这样得到的是一个字典key 是分组键、value 是对应的子表。要点默认as_indexTrue这里迭代的是分组与as_index无关。分组键里如果有NaN默认dropnaTrue会把这个组丢掉想保留分组键里的缺失值需要显式设dropnaFalse。四、合并之一纵向堆叠用 concat# pandas 1.0stacked pd.concat([df1, df2], ignore_indexTrue)concat(objs, axis0, joinouter, ignore_indexFalse, keysNone, ...)axis0纵向、axis1横向joinouter时列取并集缺的补NaNjoininner取交集ignore_indexTrue重建从 0 开始的整数索引避免重复索引keys[...]会给每段数据加一层外层索引得到MultiIndex。五、合并之二按键对齐用 mergehow取值对应 SQL结果innerINNER JOIN两边键都存在的行默认leftLEFT OUTER JOIN左表全保留rightRIGHT OUTER JOIN右表全保留outerFULL OUTER JOIN两边并集crossCROSS JOIN笛卡尔积# pandas 1.0merged pd.merge(left, right, howleft, onid, suffixes(_l, _r))要点左右键名不同时用left_on/right_on要用索引对齐就设left_indexTrue或right_indexTrue。两表有同名列但不是连接键时suffixes决定后缀默认(_x, _y)。连接键在一边不唯一时会产生笛卡尔扩张行数暴涨。可用validateone_to_one等取值让 pandas 主动检查并报错。六、合并之三按索引 join 与缺失互补# pandas 1.0a df1.join(df2, howleft) # 按索引对齐底层仍是 mergeb df1.combine_first(df2) # df1 缺失处用 df2 补DataFrame.join默认是左连接和merge默认内连接不同别混。combine_first则用于两张表互补以调用者为基准它缺的地方用另一张补上。 它按标签对齐只有双方索引/列对不上的位置才会用对方的值填充因此 最适合两份来源不同、覆盖范围互相错开的数据。如果你只想标记每行来自哪张表而不是真的拼接可以在merge里传indicatorTrue结果会多出一列_merge取值是left_only、right_only或both。排查为什么合并后少了行时这一列非常有用# pandas 1.0probe pd.merge(left, right, onid, howouter, indicatorTrue)print(probe[_merge].value_counts())先看value_counts()的输出就能立刻知道是左表独有的键多、还是右表独有的键多。七、完整示例# pandas 1.0import pandas as pddef build(orders: pd.DataFrame, users: pd.DataFrame) - pd.DataFrame:# 拆分把 user_id|sku 拆成两列split orders[key].str.split(|, expandTrue)split.columns [user_id, sku]orders pd.concat([orders.drop(columnskey), split], axis1)# 合并补上用户城市merged orders.merge(users, howleft, onuser_id,validatemany_to_one)return mergedif __name__ __main__:print(build(pd.DataFrame(), pd.DataFrame()).columns)这段示例把str.split、concat(axis1)、merge串了起来 实际使用时把空DataFrame换成真实数据即可。常见坑点str.split忘了expandTrue❌df[a].str.split(,)得到每格是列表的Series再取列会报错 ✅df[a].str.split(,, expandTrue)得到可用的多列DataFrame拿split去拆行❌ 想把一格列表拆成多行却用str.split结果每格还是一个列表 ✅ 用df.explode(items)concat后索引重复❌pd.concat([df1, df2])得到 0,1,2,0,1,2 的重复索引后续.loc[0]取到多行 ✅pd.concat([df1, df2], ignore_indexTrue)把merge和join的默认连接方向记混❌ 以为df.join(other)是内连接 ✅merge默认howinnerjoin默认howleft别混连接键有重复导致行数暴涨❌ 以为一对一结果一边键重复合并后行数翻几倍还不知道为什么 ✅ 显式传validatemany_to_one等让 pandas 帮你查基数关系concat(axis1)不按列名对齐❌ 以为横向拼接会自动按列名对齐再并入实际是按索引对齐 ✅ 横向拼接靠索引要按键对齐请用merge分组时丢掉了键里的NaN❌df.groupby(city)后城市为空的组凭空消失 ✅ 需要保留就写df.groupby(city, dropnaFalse)总结需求该用的方法易错点字符串拆多列str.split(expandTrue)漏expand列表拆多行explode误用split按组拆子表groupby迭代dropna丢组纵向堆叠concat(axis0)索引重复按键连接merge(how...)默认内连接、基数按索引对齐join默认左连接缺失互补combine_first基准方向记反拆分与合并的关键不是记函数名而是先判断拆的是列、行还是组、 合的是纵向、按键还是按索引。方向定下来函数自然就选对了。