使用Pandas自动导入文本文件末尾的目标数据表(无需硬编码跳过行数)
使用Pandas自动导入文本文件末尾的目标数据表(无需硬编码跳过行数)
嗨,我完全懂你这种被硬编码行数折腾的痛苦!每个文件都要手动数跳过多少行,效率太低了。好在你的目标数据有个非常明确的特征——它被两条全是短横线的行包裹,而且在文件的最末尾,我们完全可以利用这个特征来自动定位数据区域,不用再手动算skiprows了。
下面是具体的实现思路和代码:
核心思路
我们先遍历整个文本文件,标记出所有由短横线组成的行(也就是你的数据分隔线)。因为目标数据总是在倒数第二条分隔线之后、最后一条分隔线之前,所以只要找到这两个分隔线的位置,就能精准提取出需要的数据。
方法一:高效读取(仅打开一次文件)
这种方法把所有行读入内存,只需要打开一次文件,适合处理大文件:
import pandas as pd from io import StringIO # 第一步:读取所有行并定位分隔线 with open('Name_of_file.txt', 'r', encoding='utf-8') as f: lines = f.readlines() dash_line_indices = [] for idx, line in enumerate(lines): stripped_line = line.strip() # 过滤出真正的分隔线:全是短横线且长度足够长(避免误判短横线行) if stripped_line and all(char == '-' for char in stripped_line) and len(stripped_line) > 10: dash_line_indices.append(idx) # 第二步:确定数据的起止范围 # 目标数据在倒数第二条分隔线的下一行,到最后一条分隔线的前一行 start_idx = dash_line_indices[-2] + 1 end_idx = dash_line_indices[-1] # 第三步:提取数据并导入Pandas data_content = ''.join(lines[start_idx:end_idx]) df = pd.read_csv( StringIO(data_content), delimiter=r"\s+", # 空格分隔符,和你原来的设置一致 header=None # 如果你的数据不需要表头,保持这个;如果需要表头,看下面的说明 )
方法二:分两次读取(适合内存有限的场景)
如果文件特别大,不想一次性读入内存,可以分两次操作:
import pandas as pd # 第一步:先遍历文件找分隔线位置 dash_line_indices = [] with open('Name_of_file.txt', 'r', encoding='utf-8') as f: for idx, line in enumerate(f): stripped_line = line.strip() if stripped_line and all(char == '-' for char in stripped_line) and len(stripped_line) > 10: dash_line_indices.append(idx) # 第二步:计算需要跳过的行数和尾部行数 total_lines = len(open('Name_of_file.txt').readlines()) skip_rows = dash_line_indices[-2] + 1 skip_footer = total_lines - dash_line_indices[-1] # 第三步:读取数据 df = pd.read_csv( 'Name_of_file.txt', encoding='utf-8', delimiter=r"\s+", skiprows=skip_rows, skipfooter=skip_footer, header=None, engine='python' # 注意:skipfooter参数需要使用python引擎 )
关于表头的处理
如果你想把数据上方的多行表头(比如示例里的Spec. Spec.、Corr. cond. cond.这些行)也导入成多级表头,可以调整代码:
比如在方法一中,把start_idx设为dash_line_indices[-2] - 4(假设表头有4行),然后设置header=[0,1,2,3],这样Pandas会把这4行合并成多级列名:
start_idx = dash_line_indices[-2] - 4 # 回到表头的第一行 end_idx = dash_line_indices[-1] data_content = ''.join(lines[start_idx:end_idx]) df = pd.read_csv( StringIO(data_content), delimiter=r"\s+", header=[0,1,2,3] )
注意事项
- 我们加了
len(stripped_line) > 10的判断,是为了避免误识别那些只有少量短横线的行(比如---),你可以根据实际文件调整这个长度阈值。 - 如果你的文件里只有两条分隔线(刚好包裹目标数据),代码同样适用,因为
dash_line_indices[-2]和dash_line_indices[-1]就是这两条线的位置。
备注:内容来源于stack exchange,提问作者jjkennedy
相关产品推荐
相关产品推荐

