如何解决Pandas DataFrame使用append方法后列顺序变更并将result列追加至原列末尾
保留原CSV列顺序并追加新列的解决方案
你的问题出在两个地方:一是每次循环都重新初始化KeyBERT模型,这会极大拖慢运行速度;二是空的DataFrame使用append添加Series时,Pandas会自动按列名字母顺序排序,导致原列顺序被打乱。
下面是修正后的代码,既保留原列顺序,又优化了性能:
import pandas as pd from keybert import KeyBERT # 1. 读取原始CSV,保留原列顺序 df_info = pd.read_csv(r'./old.csv', encoding='utf-8') # 2. 只初始化一次KeyBERT模型(关键优化!不要放在循环里) model = KeyBERT('distilbert-base-nli-mean-tokens') # 3. 定义关键词提取函数,用apply批量处理,比循环iterrows高效 def get_keywords(doc): return model.extract_keywords(doc, keyphrase_ngram_range=(1, 1)) # 4. 在原DataFrame上直接添加result列,默认会追加到所有原列的最后 df_info['result'] = df_info['info'].apply(get_keywords) # 5. 保存CSV,此时列顺序就是D, info, B, A, C, result df_info.to_csv(r'./new.csv', index=False, mode='w', header=True, encoding='utf-8-sig')
为什么这个方法有效?
- 直接在原
df_info上添加新列时,Pandas会默认把新列放在所有现有列的末尾,完美符合你想要的原列顺序 + result的要求。 - 将KeyBERT模型初始化放在循环外,避免了重复加载模型的巨大性能开销,运行速度会提升很多。
- 使用
apply批量处理比iterrows循环更高效,尤其是当你的CSV行数较多时。
如果你坚持要使用循环iterrows的方式(不推荐,效率较低),可以这样修改来保留列顺序:
import pandas as pd from keybert import KeyBERT df_info = pd.read_csv(r'./old.csv', encoding='utf-8') # 提前定义目标列顺序:原列 + result target_columns = df_info.columns.tolist() + ['result'] # 初始化带有指定列的空DataFrame df_re = pd.DataFrame(columns=target_columns) # 只初始化一次模型 model = KeyBERT('distilbert-base-nli-mean-tokens') for index, row in df_info.iterrows(): doc = row['info'] a = model.extract_keywords(doc, keyphrase_ngram_range=(1, 1)) row['result'] = a # 按指定列顺序将row转为DataFrame后追加 df_re = pd.concat([df_re, pd.DataFrame([row], columns=target_columns)], ignore_index=True) df_re.to_csv(r'./new.csv', index=False, mode='w', header=True, encoding='utf-8-sig')
这个方法通过提前指定df_re的列顺序,避免了append时自动排序的问题,但性能不如第一种方法,所以优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者CR7




