Python/Pandas:如何将按特定行分段的实验数据拆分为多组列
解决按Cycle分段的仪器数据列转换问题
核心思路
因为每个Cycle的行数不固定,没法用固定切片或分组,所以得先逐行识别Cycle边界,再分别收集每个Cycle的数据,最后合并成宽表。
步骤1:逐行读取并拆分各Cycle数据
先把文件里的内容按行读,碰到以TTS开头的行就标记为新Cycle的开始,把后续的波长、吸光度数据存到对应的Cycle组里:
import pandas as pd # 初始化存储各Cycle数据的字典 cycle_dict = {} current_cycle = None temp_rows = [] # 替换成你的数据文件路径,格式支持txt/csv with open('lab_data.txt', 'r', encoding='utf-8') as f: for line in f: stripped_line = line.strip() if not stripped_line: continue # 跳过空行 # 判断是否是Cycle起始行 if stripped_line.startswith('TTS'): # 先把上一个Cycle的数据存起来 if current_cycle is not None and temp_rows: cycle_df = pd.DataFrame(temp_rows, columns=['Wavelength (nm)', 'Absorbance']) cycle_dict[current_cycle] = cycle_df # 提取Cycle标识,比如从"TTS Cycle 3"里拿到"Cycle 3" current_cycle = stripped_line.split(maxsplit=1)[1] if len(stripped_line.split())>1 else stripped_line temp_rows = [] else: # 拆分波长和吸光度,这里按空格分隔,实际按你数据的分隔符改(比如逗号用split(',')) wave, absorb = stripped_line.split() temp_rows.append([float(wave), float(absorb)]) # 别忘了存最后一个Cycle的数据 if current_cycle is not None and temp_rows: cycle_df = pd.DataFrame(temp_rows, columns=['Wavelength (nm)', 'Absorbance']) cycle_dict[current_cycle] = cycle_df
步骤2:合并成宽表(按需求生成独立列)
情况1:所有Cycle的波长完全一致(大部分仪器数据都是这种情况)
直接以第一个Cycle的波长为基准,把每个Cycle的吸光度对应加进去:
# 取第一个Cycle的波长作为基础列 first_cycle_name = next(iter(cycle_dict.keys())) final_df = cycle_dict[first_cycle_name][['Wavelength (nm)']].rename(columns={ 'Wavelength (nm)': f'Wavelength ({first_cycle_name})' }) # 遍历每个Cycle,添加吸光度列 for cycle_name, df in cycle_dict.items(): final_df[f'Absorbance ({cycle_name})'] = df['Absorbance'] # 查看结果 print(final_df.head())
情况2:不同Cycle的波长不一致(少见但需处理)
用外连接合并,保留所有波长数据,缺失值可按需填充:
final_df = pd.DataFrame() for cycle_name, df in cycle_dict.items(): # 重命名当前Cycle的列 renamed_df = df.rename(columns={ 'Wavelength (nm)': f'Wavelength ({cycle_name})', 'Absorbance': f'Absorbance ({cycle_name})' }) # 外连接合并 if final_df.empty: final_df = renamed_df else: final_df = pd.merge(final_df, renamed_df, how='outer', left_index=True, right_index=True) # 缺失值填充,这里填0,你也可以用NaN或其他值 final_df = final_df.fillna(0)
注意事项
- 数据分隔符:如果你的数据是逗号分隔,把
split()改成split(','),或者根据实际调整拆分逻辑 - Cycle标识提取:如果起始行格式不是
TTS Cycle X,可以用正则表达式匹配,比如import re; current_cycle = re.search(r'Cycle \d+', stripped_line).group() - 文件编码:如果读取时乱码,把
encoding='utf-8'改成encoding='gbk'或其他对应编码
内容的提问来源于stack exchange,提问作者Adenai
相关产品推荐
相关产品推荐

