首页 > 解决方案 > 如何从复杂格式的文件中读取数据?

问题描述

我从需要读取的文件中输出数据。它是一个矩阵,但在输出文件中以一种困难的方式布局。见下文 - 这是一个 5x5 矩阵,但仅打印非零元素:

SCATTER MOMENT      1

GROUP      1 FIRST      1 LAST    5
  1.000000E-00  2.000000E-00  3.000000E-00  4.000000E-00  5.000000E-00
GROUP      2 FIRST      2 LAST    5
  2.000000E-00  3.000000E-00  4.000000E-00  5.000000E-00
GROUP      3 FIRST      3 LAST    4
  3.000000E-00  4.000000E-00
GROUP      4 FIRST      4 LAST    5
  4.000000E-00  5.000000E-00
GROUP      5 FIRST      3 LAST    5
  3.000000E-00  4.000000E-00  5.000000E-00
  
SCATTER MOMENT      2

所以这应该是这个矩阵,加上未打印的零:

1 2 3 4 5
0 2 3 4 5
0 0 3 4 0
0 0 0 4 5
0 0 3 4 5

我需要编写一个 Python 脚本,它将:

  1. 搜索“SCATTER MOMENT 1”作为数据起点标识符
  2. 创建并填充一个矩阵,从第一个到最后一个组读取数据并在其他任何地方插入零
  3. 为每个 GROUP 执行此操作

尽管此示例是 5x5,但矩阵可以是任何形状。到目前为止,我只搜索了开始标识符,任何关于读取数据的指针都将不胜感激。

start_identifier = "SCATTER MOMENT      1"
end_identifier = "SCATTER MOMENT      2"

def read_data_from_file(file_name, start_identifier, end_identifier):
    list_of_results = []
    with open(file_name) as f:
            t=f.read()
    t=t[t.find(start_identifier)+len(start_identifier):t.find(end_identifier)]
            t=t.replace('\n', '').split()
            t=[float(i) for i in t if not i.isidentifier()]
            list_of_results.extend(t)
    return(list_of_results) 

我之前发布了这个问题,但已经重新措辞并包含了一个更好的数据示例。

标签: pythonmatrix

解决方案


您可以使用正则表达式来匹配包含组信息的行并提取其中所需的值。由于在读取所有数据行之前您不会知道矩阵的维度,因此需要一个后处理步骤来延长任何太短的行。

import re

group_pattern = re.compile(r"GROUP +\d+ FIRST +(?P<first>\d+) LAST +(?P<last>\d+)")

def read_data_from_file(file_name):
    results = []
    longest = 0
    with open(file_name) as file:
        for line in file:
            match = group_pattern.search(line)
            if match:
                first = int(match.group('first'))
                last = int(match.group('last'))
                data = [float(value) for value in next(file).split()]
                row = [0.0] * last
                for i, value in enumerate(data, start=first-1):
                    row[i] = value
                longest = max(longest, len(row))
                results.append(row)

    for row in results:
        if len(row) < longest:
            row.extend([0.0] * (longest-len(row)))
    return results

results = read_data_from_file('difficult-format.dat')
for row in results:
    print(row)

打印结果:

[1.0, 2.0, 3.0, 4.0, 5.0]
[0.0, 2.0, 3.0, 4.0, 5.0]
[0.0, 0.0, 3.0, 4.0, 0.0]
[0.0, 0.0, 0.0, 4.0, 5.0]
[0.0, 0.0, 3.0, 4.0, 5.0]

推荐阅读