You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从TXT提取质谱数据并导入CSV的技术问题求助

问题

我有一份质谱格式的TXT文件,数据结构如下:

ScanHeader # 1
position = 1, start_mass= 2.000000, end_mass = 535.010058
start_time = 0.034048, end_time = 0.000000, packet_type = 24
num_readings = 114, integ_intens = 14276257.301926, data packet pos = 1026
uScanCount = 0, PeakIntensity = 6799450.500000, PeakMass = 18.045876
Scan Segment = 0, Scan Event = 0
Precursor Mass 
Collision Energy 
Isolation width 
Polarity positive, Cenrtoid Data, Full Scan Type, MS Scan
SourceFragmentation Any, Type Ramp, Values = 0, Mass Ranges = 0
Turbo Scan Any, IonizationMode ElectronImpact, Corona Any
Detector Any, Value = 0.00, ScanTypeIndex = -1
DataPeaks

Packet # 0, intensity = 3691.226074, mass/position = 2.112536
saturated = 0, fragmented = 0, merged = 0

Packet # 1, intensity = 42881.203125, mass/position = 3.466080
saturated = 0, fragmented = 0, merged = 0

Packet # 2, intensity = 3006256.000000, mass/position = 4.184193
saturated = 0, fragmented = 0, merged = 0

我期望将其转换为指定结构的CSV文件,但尝试regex和read_csv方法均未得到理想结果。通过regex已提取到所需数据,但无法正确组装到DataFrame中,现有代码如下:

from tabulate import tabulate
import re 

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data = re.findall(r'\d*last_scan = \d*\d.\d*', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data1 = re.findall(r'\d* start_time = \d*\d.\d*', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data2 = re.findall(r'\d* end_time = \d*\d.\d*', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data3 = re.findall(r'\d*low_mass = \d*\d.\d*', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data4 = re.findall(r'\d*high_mass = \d*\d.\d*', newfile.read())
    
with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data5 = re.findall(r'\d*ScanHeader # \d', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data6 = re.findall(r'\d*Packet # \d*', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data7 = re.findall(r'\d* intensity = \d*\d.\d*', newfile.read())

with open('2020-06-23-Didecylamine-deriv-0,1uL.txt') as newfile:
    data8 = re.findall(r'\d* mass/position = \d*\d.\d*', newfile.read())

import pandas as pd

data = {'Scanheader': [data5],
        'Packet Number': [data6],
        'Intensity': [data7], 
        'Mass/Position': [data8]
        }

df = pd.DataFrame(data) 
df.to_csv('2020-06-23-Didecylamine-deriv-0,1uL.csv', index=False) 

当前生成的CSV不符合预期格式,恳请提供改进建议。

解决方案

核心问题分析

你的代码存在两个关键问题:

  • 多次重复打开同一文件,效率低下且易出错;
  • 提取的数据是独立列表,未建立**扫描头(ScanHeader)与对应数据包(Packet)**的关联,导致DataFrame结构混乱。

改进后的代码

import re
import pandas as pd

# 一次性读取文件内容,避免重复IO操作
with open('2020-06-23-Didecylamine-deriv-0,1uL.txt', 'r') as f:
    content = f.read()

# 匹配所有扫描头及其后续的数据包块
scan_pattern = re.compile(
    r'ScanHeader # (\d+).+?DataPeaks\n\n(.*?)(?=\n\nScanHeader|\Z)',
    re.DOTALL
)
scans = scan_pattern.findall(content)

# 存储最终结构化数据的列表
final_data = []

# 遍历每个扫描头,处理对应的数据包
for scan_num, packets_text in scans:
    # 匹配当前扫描头下的所有数据包核心信息
    packet_pattern = re.compile(
        r'Packet # (\d+), intensity = ([\d.]+), mass/position = ([\d.]+)',
        re.MULTILINE
    )
    packets = packet_pattern.findall(packets_text)
    
    # 将每个数据包与所属扫描头绑定,添加到最终列表
    for packet_num, intensity, mass_pos in packets:
        final_data.append({
            'ScanHeader': int(scan_num),
            'Packet Number': int(packet_num),
            'Intensity': float(intensity),
            'Mass/Position': float(mass_pos)
        })

# 转换为DataFrame并保存为CSV
df = pd.DataFrame(final_data)
df.to_csv('2020-06-23-Didecylamine-deriv-0,1uL.csv', index=False)

代码说明

  1. 一次性读取文件:仅打开文件一次,读取全部内容,大幅提升效率;
  2. 分层正则匹配:
    • 外层正则匹配每个完整扫描块,包含扫描头编号和对应所有数据包的文本;
    • 内层正则从扫描块中提取每个数据包的编号、强度、质荷比/位置;
  3. 建立数据关联:每个数据包与所属扫描头绑定,确保每行数据对应一个数据包+扫描头的组合,符合CSV的行式结构;
  4. 数据类型转换:将提取的字符串转为数值类型(int/float),方便后续分析。

扩展优化(可选)

如果需要提取扫描头中的其他字段(如start_time、end_mass等),可以修改扫描块的正则表达式:

scan_pattern = re.compile(
    r'ScanHeader # (\d+)\n'
    r'position = \d+, start_mass= ([\d.]+), end_mass = ([\d.]+)\n'
    r'start_time = ([\d.]+), end_time = ([\d.]+), packet_type = \d+\n'
    r'.+?DataPeaks\n\n(.*?)(?=\n\nScanHeader|\Z)',
    re.DOTALL
)

遍历扫描块时,将这些字段也添加到字典中即可。

内容的提问来源于stack exchange,提问作者user19870417

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:45:33