Pandas中如何同时拆分不等长的phones与emails列?
多列不等条目拆分多行解决方案
需要将DataFrame中的phones和emails两列拆分成多行,核心要求是:两列条目数不一致时,以条目数多的列为基准生成行,条目数少的列按序填充后剩余行留空。单独拆分一列可实现,但同时拆分时出现报错。
示例数据
| many columns | phones | emails |
|---|---|---|
| row 1 | A,B,C | A,B |
| row 2 | D,E,F |
预期结果
| many columns | phones | emails |
|---|---|---|
| row 1 | A | A |
| row 1 | B | B |
| row 1 | C | |
| row 2 | D | |
| row 2 | E | |
| row 2 | F |
尝试代码及报错
# 将单元格内容转为列表而非字符串 df0['phones'] = df0['phones'].str.split(";", expand=False) df0['emails'] = df0['emails'].str.split(",", expand=False) df0 = df0.apply(pd.Series.explode) # 无法运行
运行后报错:
ValueError: cannot reindex on an axis with duplicate labels
解决方案
问题出在apply(pd.Series.explode)会同时对两列执行拆分,但两列长度不一致时会导致索引冲突。正确做法是先计算每行需要扩展的行数(取两列列表的最大长度),再逐行扩展并填充对应值:
import pandas as pd # 构造示例数据 data = { 'many columns': ['row 1', 'row 2'], 'phones': ['A,B,C', ''], 'emails': ['A,B', 'D,E,F'] } df0 = pd.DataFrame(data) # 处理空值,将字符串分割为列表(空值转为空列表) df0['phones'] = df0['phones'].apply(lambda x: x.split(',') if x.strip() else []) df0['emails'] = df0['emails'].apply(lambda x: x.split(',') if x.strip() else []) # 计算每行需要扩展的行数(取两列列表的最大长度) df0['expand_len'] = df0.apply(lambda row: max(len(row['phones']), len(row['emails'])), axis=1) # 定义函数:将单行扩展为指定长度的多行,并填充对应列的值 def expand_row(row): # 复制其他列到对应行数 base_df = pd.DataFrame({ col: [row[col]] * row['expand_len'] for col in df0.columns if col not in ['phones', 'emails'] }) # 填充phones列,不足的行补空字符串 base_df['phones'] = row['phones'] + [''] * (row['expand_len'] - len(row['phones'])) # 填充emails列,不足的行补空字符串 base_df['emails'] = row['emails'] + [''] * (row['expand_len'] - len(row['emails'])) return base_df # 合并所有扩展后的行,重置索引 result_df = pd.concat([expand_row(row) for _, row in df0.iterrows()], ignore_index=True) # 删除临时的扩展长度列 result_df = result_df.drop('expand_len', axis=1) print(result_df)
运行后即可得到符合预期的结果。
内容的提问来源于stack exchange,提问作者Rachel S
相关产品推荐
相关产品推荐

