如何仅使用 python 从文件中提取数据

How to extract data from file using only python

我有一个数据文件看起来像::

# GROMACS
#
@    title "GROMACS Energies"
@    xaxis  label "Time (ps)"
@    yaxis  label "(K)"
@TYPE xy
@ view 0.15, 0.15, 0.75, 0.85
@ legend on
@ legend box on
@ legend loctype view
@ legend 0.78, 0.8
@ legend length 2
@ s0 legend "Temperature"
    0.000000  301.204895
    1.000000  299.083496
    2.000000  293.100250
    3.000000  301.090637
    4.000000  293.024811
    5.000000  297.068481
    6.000000  298.065125
    7.000000  300.354370
    8.000000  304.322693
    9.000000  297.093170
   10.000000  297.186615
   11.000000  298.112732
   12.000000  293.396545
   13.000000  295.803162
   14.000000  293.432037
   15.000000  298.306702
   16.000000  297.545715
   17.000000  294.283875
   18.000000  295.527771
   19.000000  297.193665

我想做的是提取 @ s0 legend "Temperature" 表达式下方的所有数据点并将其放入数据帧中,或者只是一个可以通过 python 轻松访问的数据结构。我目前正在结合使用 awk 和 python 来执行此操作。

我先做 awk '/@ s0 legend/{flag=1; next} flag' temp.xvg > temp.dat 获取只有两列数据的 temp.dat 文件。然后,我使用 panda read_csv 将数据作为列来执行我的分析。

我想省去将临时文件写入磁盘以将信息发送到 python 的中间人。这可能吗?我可以通过简单的 python 脚本提取数据列吗?

python是单行本。类似于:

file_data = [list(map(float,x.strip().split())) for x in open("filedata.txt","rt") if x.strip()[:1] not in "@#"]

读入文件,去除空格,去除非数据行,拆分字符串,转换为浮点数。结果是数据对列表。

在 python 中等效的程序是:

import re
# Using readlines()
file1 = open('temp.xvg', 'r')
Lines = file1.readlines()
 
count = 0
# Strips the newline character
for line in Lines:
    if count==0:
        x=re.search("^@ s0 legend",line)
        if x: # FOUND!!!
            count += 1

    else:
        print("{}".format(line.strip()))

您可以将其另存为program.py。然后执行:

python2 program.py

你会得到这个输出:

0.000000  301.204895
1.000000  299.083496
2.000000  293.100250
3.000000  301.090637
4.000000  293.024811
5.000000  297.068481
6.000000  298.065125
7.000000  300.354370
8.000000  304.322693
9.000000  297.093170
10.000000  297.186615
11.000000  298.112732
12.000000  293.396545
13.000000  295.803162
14.000000  293.432037
15.000000  298.306702
16.000000  297.545715
17.000000  294.283875
18.000000  295.527771
19.000000  297.193665

您可以只读取文件中的行,直到到达 legend 行;然后在文件的余额上使用 read_csv。在阅读开头的行时,您还可以提取 xaxis 和 yaxis 标签以用作列名。例如:

import pandas as pd
import re

with open('test.dat', 'r') as f:
    for line in f:
        m = re.search(r'xaxis\s+label\s+"([^"]+)"', line)
        if m is not None:
            xaxis = m.group(1)
        m = re.search(r'yaxis\s+label\s+"([^"]+)"', line)
        if m is not None:
            yaxis = m.group(1)
        if line.startswith('@ s0 legend'):
            break
    df = pd.read_csv(f, names=[xaxis, yaxis], delim_whitespace=True)
    f.close()
    
print(df)

输出

    Time (ps)         (K)
0         0.0  301.204895
1         1.0  299.083496
2         2.0  293.100250
3         3.0  301.090637
4         4.0  293.024811
5         5.0  297.068481
6         6.0  298.065125
7         7.0  300.354370
8         8.0  304.322693
9         9.0  297.093170
10       10.0  297.186615
11       11.0  298.112732
12       12.0  293.396545
13       13.0  295.803162
14       14.0  293.432037
15       15.0  298.306702
16       16.0  297.545715
17       17.0  294.283875
18       18.0  295.527771
19       19.0  297.193665