如何对含随机列名、随机长度列表的Pandas DataFrame批量展开去重?
问题描述
我通过网站API生成了一个带随机表头的Pandas DataFrame,需要对多个列中长度随机、列名随机的列表同时执行explode操作,之后去除重复值且不产生数据间隙。
处理前数据
Random Key 1 Random Key 2 Random Key 3 Random Key 4 Random Key 5 list1 list2 list3 list4 list5
(注:list1-list5为不同长度的列表,例如list1长度4、list2长度6、list3长度3、list4长度7、list5长度2)
预期结果
Random Key 1 Random Key 2 Random Key 3 Random Key 4 Random Key 5 string1.1 string2.1 string3.1 string4.1 string5.1 string1.2 string2.2 string3.2 string4.2 string5.2 string1.3 string2.3 string3.3 string4.3 string1.4 string2.4 string4.4 string2.5 string4.5 string2.6 string4.6 string4.7
当前尝试代码
userList = pd.DataFrame.from_dict(data=user, orient="index") userList = pd.DataFrame.transpose(userList) allQuarters = list(set(allQuarters)) for quarters in allQuarters: userList = userList.explode(quarters) for headers in userList: userList.loc[userList[headers].duplicated(), headers] = ""
注:userList是包含随机列名和未知长度列表的DataFrame,allQuarters是我用来检测含列表的列的方法。
解决方案
你的代码存在两个核心问题:
- 循环执行
explode会持续增加行数,导致后续去重逻辑混乱 - 嵌套循环遍历所有列去重,会错误清空已处理列的重复值
以下是正确的实现步骤:
1. 自动识别含列表的列
无需手动指定列名,自动检测所有值为列表类型的列:
list_cols = [col for col in userList.columns if isinstance(userList[col].iloc[0], list)]
2. 批量执行explode操作
一次性对所有目标列执行explode,Pandas会自动对齐行数,短列表的缺失行用NaN填充:
userList_exploded = userList.explode(list_cols, ignore_index=True)
3. 去除重复值并替换为空字符串
对每一列单独处理,仅清空该列重复出现的非NaN值(保留第一次出现的内容):
for col in userList_exploded.columns: # 标记重复值(保留首次出现的项) dup_mask = userList_exploded[col].duplicated(keep='first') # 仅替换非NaN的重复值为空字符串 userList_exploded.loc[dup_mask & userList_exploded[col].notna(), col] = ""
完整可运行代码
import pandas as pd # 模拟API返回的字典数据 user = { "Random Key 1": ["string1.1", "string1.2", "string1.3", "string1.4"], "Random Key 2": ["string2.1", "string2.2", "string2.3", "string2.4", "string2.5", "string2.6"], "Random Key 3": ["string3.1", "string3.2", "string3.3"], "Random Key 4": ["string4.1", "string4.2", "string4.3", "string4.4", "string4.5", "string4.6", "string4.7"], "Random Key 5": ["string5.1", "string5.2"] } # 生成初始DataFrame userList = pd.DataFrame.from_dict(user, orient="index").T # 识别列表列 list_cols = [col for col in userList.columns if isinstance(userList[col].iloc[0], list)] # 批量explode userList_exploded = userList.explode(list_cols, ignore_index=True) # 处理重复值 for col in userList_exploded.columns: dup_mask = userList_exploded[col].duplicated(keep='first') userList_exploded.loc[dup_mask & userList_exploded[col].notna(), col] = "" # 输出结果 print(userList_exploded)
关键说明
- 批量
explode避免了多次循环导致的行数膨胀,保证数据对齐准确 - 逐列处理重复值,确保仅清空当前列的重复项,不干扰其他列数据
- 保留
NaN对应的空白位置,完全匹配预期结果的格式
内容的提问来源于stack exchange,提问作者InfinitySwordofDiamond
相关产品推荐
相关产品推荐

