Pandas按不同列组截取字符重命名列名遇覆盖问题求助
处理DataFrame多组列名批量重命名的问题
问题场景
需要对DataFrame的不同列组按指定规则重命名:
- 前10列:截取列名从第75位开始的字符
- 19-29列:截取列名从第38位开始的字符
还需处理另外5组类似规则的列,但使用以下代码时,19-29列的重命名操作会错误覆盖前面的列名:
# 处理前10列 new_names = dfr.iloc[:,0:10].rename(columns=lambda x: x[75:]).columns #first 10 columns dfr.rename(columns=dict(zip(dfr.columns,new_names)),inplace=True) # 处理19-29列 new_names = dfr.iloc[:,19:29].rename(columns=lambda x: x[38:]).columns #from 19-29 columns dfr.rename(columns=dict(zip(dfr.columns,new_names)),inplace=True)
错误原因
你的代码中,dict(zip(dfr.columns, new_names))是把整个DataFrame的列名列表和仅包含目标列的new_names做配对,这会导致列名映射错位——new_names的长度远小于总列数,zip会循环匹配,最终错误覆盖前面的列名,而不是只修改目标列组。
解决方案
正确的思路是:针对每个列组单独生成「原列名→新列名」的映射,将所有规则的映射合并到一个字典中,最后统一执行重命名操作。这样既不会误改其他列,也能轻松扩展更多规则。
实现代码
# 定义所有列组的处理规则:(列索引范围, 截取起始位置) # 可直接在这里添加另外5组规则 rename_rules = [ (slice(0, 10), 75), # 前10列:从第75位开始截取 (slice(19, 29), 38), # 19-29列:从第38位开始截取 # 示例:添加其他规则 # (slice(30, 40), 20), # (slice(50, 60), 15), ] # 生成统一的重名字典 rename_dict = {} for col_range, start_pos in rename_rules: # 获取当前规则对应的列名 target_columns = dfr.columns[col_range] # 为每个列生成映射 for col in target_columns: rename_dict[col] = col[start_pos:] # 执行重命名 dfr.rename(columns=rename_dict, inplace=True)
简化写法(字典推导式)
如果追求代码简洁,可以用嵌套字典推导式一次性生成映射:
rename_rules = [ (slice(0, 10), 75), (slice(19, 29), 38), # 其他规则 ] rename_dict = {col: col[start] for col_range, start in rename_rules for col in dfr.columns[col_range]} dfr.rename(columns=rename_dict, inplace=True)
优势说明
- 仅修改目标列组,不会影响其他列的名称
- 规则集中管理,添加/修改列组处理逻辑只需更新
rename_rules列表 - 避免多次调用
rename导致的性能损耗和错误
内容的提问来源于stack exchange,提问作者user16239103
相关产品推荐
相关产品推荐

