Pandas批量处理VCF文件:仅输出Aminoacids列问题排查
VCF文件处理异常:仅保存单列的问题分析与修复
需求与原始代码
需要批量处理文件夹中的VCF文件,完成两个操作:
- 重命名表头(将
P列改为Aminoacids) - 对
Gene和Aminoacids列按第一个|分割取值,并移除Aminoacids列中的p.前缀
原始代码如下:
path = "/home/kristina/snpeff_analysis/a.a/result/Ann.vcf/TEST_P.G_ann.vcf/PLAY.TEST" all_files = glob.glob(path + "/*_G.P.vcf") #print(all_files) aa_df = [] for filename in all_files: aa_df = pd.read_csv(filename, sep='\t') new_header = {'Gene':'Gene', 'P':'Aminoacids'} aa_df.rename(columns=new_header, inplace=True) aa_df.to_csv(filename, index=False, sep='\t') #%% #split & replace def get_element(my_list, position): return my_list[position] df = aa_df for filename in all_files: df.Gene.str.split('|').apply(get_element, position=0), df.Aminoacids.str.split('|').apply(get_element, position=0).str.replace('p.','').to_csv(filename, index=False, sep='\t')
原始文件示例
Gene Aminoacids gyrA|Rv0007|ppiA|dnaN|recF|Rv0004|gyrB|Rv0008c p.Ser95Thr|.|.|.|.|.|.|. rpoB|rpoC|atsD|vapB8|vapC8|Rv0666 p.His445Asp|.|.|.|.|. Rv1313c|Rv1314c|atpC|Rv1312|murA|ogt|rrs .|.|.|.|.|.|. tlyA|ppnK|recN|Rv1697|mctB|mpg|tyrS|lprJ|Rv1691|Rv1692|Rv1693 p.Leu11Leu|.|.|.|.|.|.|.|.|.|.
问题现象
- 运行代码后,保存的文件仅包含处理后的
Aminoacids列:
Aminoacids Ser95Thr His445Asp . Leu11Leu
- 但将最后一行改为调用
.head()时,交互窗口能正确显示Gene和Aminoacids两列的处理结果:
(0 gyrA 1 rpoB 2 Rv1313c 3 tlyA Name: Gene, dtype: object, <bound method NDFrame.head of 0 Ser95Thr 1 His445Asp 2 . 3 Leu11Leu Name: Aminoacids, dtype: object>)
错误原因与修复方案
核心错误点
- 循环复用错误的DataFrame:第一个循环结束后,
aa_df仅保留最后一个文件的数据,第二个循环处理所有文件时,全程使用的是最后一个文件的df,逻辑完全错误。 - 仅对单列执行保存操作:最后一行代码中,你生成了两个处理后的Series,但仅对第二个Series(
Aminoacids)调用了to_csv,因此只有这一列被保存。
修复后的代码
import glob import pandas as pd path = "/home/kristina/snpeff_analysis/a.a/result/Ann.vcf/TEST_P.G_ann.vcf/PLAY.TEST" all_files = glob.glob(path + "/*_G.P.vcf") def get_element(my_list, position): return my_list[position] # 合并两个循环,逐个处理每个文件 for filename in all_files: # 读取当前文件 df = pd.read_csv(filename, sep='\t') # 重命名表头(仅修改需要变更的列) df.rename(columns={'P': 'Aminoacids'}, inplace=True) # 处理Gene列:按|分割后取第一个元素 df['Gene'] = df['Gene'].str.split('|').apply(get_element, position=0) # 处理Aminoacids列:分割取第一个元素并移除p.前缀 df['Aminoacids'] = df['Aminoacids'].str.split('|').apply(get_element, position=0).str.replace('p.', '', regex=False) # 保存完整的处理后DataFrame df.to_csv(filename, index=False, sep='\t')
额外优化说明
- 合并了两个循环,避免重复读写文件,提升效率。
- 重命名表头时仅保留需要修改的映射(
P→Aminoacids),无需冗余的Gene:Gene。 - 使用
regex=False确保str.replace仅替换字面量p.,避免正则匹配意外替换其他内容。
内容的提问来源于stack exchange,提问作者Pocket_sunshine
相关产品推荐
相关产品推荐

