如何使用Pandas按空行拆分含前置跳行的textfile.qdp多数据集并分色绘图
核心问题原因
你之前读取得到单DataFrame的根本原因,是设置了**skip_blank_lines=True:这个参数会让pandas直接跳过所有空行,完全丢失了用来标记不同数据集边界的分隔信息,自然没法区分独立数据集。
另外你参考的代码里出现的*dat**语法,是Python2时期的旧写法,在Python3环境下直接运行必然触发Invalid syntax报错,不能直接照搬适配。
完整实现流程
1. 提前保留空行的边界信息
不要直接用pandas一把读全文件,先逐行遍历文件,把空行的位置记下来作为数据集的分割点,避免提前丢失分隔信息。
首先导入需要的库、定义列名:
import pandas as pd import matplotlib.pyplot as plt from io import StringIO # 自定义8位列名 col_names = ['e', 'de', 'y', 'y_err', 'total', 'model1', 'model2', 'model3']
接着逐行读取文件、定位分割点:
file_path = "textfile.qdp" # 读取文件内容 with open(file_path, 'r') as f: # 跳过开头3行无效内容 for _ in range(3): f.readline() # 读取剩余所有行,保留原始空行的位置 raw_lines = f.readlines() # 找到所有空行的索引位置(即数据集分隔标识) split_lines = [idx for idx, line in enumerate(raw_lines) if line.strip() == ''] # 按空行位置把内容切成独立的数据集块 dataset_blocks = [] block_start = 0 for split_pos in split_lines: # 跳过连续空行导致的空块 if split_pos == block_start: block_start = split_pos + 1 continue current_block = raw_lines[block_start:split_pos] if current_block: # 过滤掉长度为0的空块 dataset_blocks.append(current_block) block_start = split_pos + 1 # 处理最后一个空行后面的收尾数据集 if block_start < len(raw_lines): dataset_blocks.append(raw_lines[block_start:])
2. 逐块生成独立DataFrame
把每个拆分出来的行块转成临时字符串流,喂给pandas读取为独立DataFrame:
datasets = [] for block in dataset_blocks: # 把行块拼接成完整字符串,转成内存文件流 block_content = ''.join(block) df = pd.read_csv( StringIO(block_content), sep=r'\s+', # 匹配任意长度的空格/制表符分隔,避免列错位 names=col_names ) datasets.append(df)
这里用\s+正则作为分隔符,比写死单空格更适配QDP格式文件的常见格式问题——比如多空格、制表符分隔的情况,不会导致列解析错位。
3. 分色绘制误差棒图
遍历生成的独立DataFrame列表,搭配不同配色绘制每个数据集的误差棒:
# 从内置色卡取不同颜色 plot_colors = plt.cm.tab10(range(len(datasets))) plt.figure(figsize=(8, 6)) for idx, df in enumerate(datasets): plt.errorbar( x=df['e'], y=df['y'], xerr=df['de'], yerr=df['y_err'], fmt='o', color=plot_colors[idx], capsize=3, label=f'数据集 {idx+1}' ) plt.xlabel('e') plt.ylabel('y') plt.legend() plt.show()
常见注意事项
- 不要在最开始用
read_table的时候就开启skip_blank_lines=True,这个参数会彻底删除空行的位置信息,完全失去拆分边界的依据。 - 不要直接照搬带
*dat的旧示例代码,那是Python2的文件解包写法,在Python3中会触发语法错误。 - 如果存在连续多个空行分隔数据集的情况,上面的代码已经做了兼容处理,不会生成空的无效DataFrame。
内容的提问来源于stack exchange,提问作者Py-ser
相关产品推荐
相关产品推荐

