Объединение и табуляция нескольких блоков текста - PullRequest
3 голосов
/ 19 июня 2020

Проблема:

Мне нужен общий c подход к следующей проблеме. Для одного из многих файлов мне удалось получить большой блок текста, который принимает форму:

                                                 Index
                         1         2         3         4         5         6
 eigenvalues:        -15.439    -1.127    -0.616    -0.616    -0.397     0.272
   1  H 1   s        0.00077  -0.03644   0.03644   0.08129  -0.00540   0.00971
   2  H 1   s        0.00894  -0.06056   0.06056   0.06085   0.04012   0.03791
   3  N     s        0.98804  -0.11806   0.11806  -0.11806   0.15166   0.03098
   4  N     s        0.09555   0.16636  -0.16636   0.16636  -0.30582  -0.67869
   5  N     px       0.00318  -0.21790  -0.50442   0.02287   0.27385   0.37400
                         7         8         9        10        11        12
 eigenvalues:          0.373     0.373     1.168     1.168     1.321     1.415
   1  H 1   s       -0.77268   0.00312  -0.00312  -0.06776   0.06776   0.69619
   2  H 1   s       -0.52651  -0.03358   0.03358   0.02777  -0.02777   0.78110
   3  N     s       -0.06684   0.06684  -0.06684  -0.01918   0.01918   0.01918
   4  N     s        0.23960  -0.23960   0.23961  -0.87672   0.87672   0.87672
   5  N     px       0.01104  -0.52127  -0.24407  -0.67837  -0.35571  -0.01102
                        13        14        15
 eigenvalues:          1.592     1.592     2.588
   1  H 1   s        0.01433   0.01433  -0.94568
   2  H 1   s       -0.18881  -0.18881   1.84419
   3  N     s        0.00813   0.00813   0.00813
   4  N     s        0.23298   0.23298   0.23299
   5  N     px      -0.08906   0.12679  -0.01711

Проблема в том, что мне нужно извлечь только коэффициенты, и мне нужно иметь возможность переформатировать таблицу, чтобы коэффициенты можно было читать в строках, а не в столбцах. Результирующий массив имел бы форму:

[[0.00077, 0.00894, 0.98804, 0.09555, 0.00318]
 [-0.03644, -0.06056, -0.11806, 0.16636, -0.21790]
 [0.03644, 0.06056, 0.11806, -0.16636, -0.50442]
 [-0.00540, 0.04012, 0.15166, -0.30582, 0.27385]
 [0.00971, 0.03791, 0.03098, -0.67869, 0.37400]
 [-0.77268, -0.52651, -0.06684, 0.23960, 0.01104]
 [0.00312, -0.03358, 0.06684, -0.23960, -0.52127
 ...
 [0.01433, -0.18881, 0.00813, 0.23298, 0.12679]
 [-0.94568, 1.84419, 0.00813, 0.23299, -0.01711]]

Это было бы для меня управляемым, если бы не тот факт, что количество столбцов меняется с разными файлами.


То, что я пробовал:

Ранее мне удалось получить собственные значения с помощью:

eigenvalues = []
with open('text', 'r+') as f:
    for n, line in enumerate(f):
        if (n >= start_section) and (n <= end_section):
            if 'eigenvalues' in line:
                eigenvalues.append(line.split()[1:])

flatten = [item for sublist in eigenvalues for item in sublist]
$ ['-15.439', '-1.127', '-0.616', '-0.616', '-0.397', '0.272', '0.373', '0.373', '1.168', '1.168', '1.321', '1.415', '1.592', '1.592', '2.588']

Итак, попробовав несколько вариантов этого, и в большинстве недавний подход, который я пробовал:

dir = {}
with open('text', 'r+') as f:
    for n, line in enumerate(f):
        if (n >= start_section) and (n <= end_section):
            for i in range(1, number_of_coefficients+1):
                if str(i) in line.split()[0]:
                    if line.split()[1].isdigit() == False:
                        if line.split()[3] in ['s', 'px', 'py', 'pz']:
                            dir[str(i)].append(line.split()[4:])
                        else:
                            dir[str(i)].append(line.split()[3:])

Который, казалось, приблизил меня, однако я получил странное дублирование чисел в случайном порядке. Идея заключалась в том, что затем я смогу преобразовать словарь в массив.

ПОМОГИТЕ !!


РЕДАКТИРОВАТЬ: буквы в 3-м и иногда 4-м столбце также являются переменными (меняются с, s, px, py, pz).

1 Ответ

3 голосов
/ 19 июня 2020

Вот один из способов сделать это. Этот подход имеет несколько примечательных аспектов.

Во-первых, и это ключевой момент, он обрабатывает данные по разделам, а не по строкам. Для этого вам нужно написать код для чтения строк ввода, а затем передать их остальной части программы в значимых разделах. Довольно часто этот предварительный шаг радикально упрощает задачу синтаксического анализа.

Во-вторых, как только у нас есть «строки» коэффициентов, стоящих перед разделом, другая задача состоит в том, чтобы переориентировать данные - в частности, чтобы транспонировать их. Я подумал, что кто-то умнее меня уже нашел отличный способ сделать это в Python, и StackOverflow не разочаровал.

В-третьих, есть разные способы получить коэффициенты из раздела входных строк , но этот тип вывода данных с фиксированной шириной в виде отчета имеет полезную характеристику c, которая может помочь при синтаксическом анализе: все выровнено по вертикали. Поэтому вместо того, чтобы думать об умном способе получения коэффициентов, мы просто берем интересующие столбцы - line[20:].

import sys

def get_section(fh):
    # Takes an open file handle.
    # Yields each section of lines having coefficients.
    lines = []
    start = False
    for line in fh:
        if 'eigenvalues' in line:
            start = True
            if lines:
                yield lines
                lines = []
        elif start:
            lines.append(line)
            if 'px' in line:
                start = False
    if lines:
        yield lines

def main():
    coeffs = []
    with open(sys.argv[1]) as fh:
        for sect in get_section(fh):
            # Grab the rows from a section.
            rows = [
                [float(c) for c in line[20:].split()]
                for line in sect
            ]
            # Transpose them. See https://stackoverflow.com/questions/6473679
            transposed = list(map(list, zip(*rows)))
            # Add to the list-of-lists of coefficients.
            coeffs.extend(transposed)

    # Check.
    for cs in coeffs:
        print(cs)

main()

Вывод:

[0.00077, 0.00894, 0.98804, 0.09555, 0.00318]
[-0.03644, -0.06056, -0.11806, 0.16636, -0.2179]
[0.03644, 0.06056, 0.11806, -0.16636, -0.50442]
[0.08129, 0.06085, -0.11806, 0.16636, 0.02287]
[-0.0054, 0.04012, 0.15166, -0.30582, 0.27385]
[0.00971, 0.03791, 0.03098, -0.67869, 0.374]
[-0.77268, -0.52651, -0.06684, 0.2396, 0.01104]
[0.00312, -0.03358, 0.06684, -0.2396, -0.52127]
[-0.00312, 0.03358, -0.06684, 0.23961, -0.24407]
[-0.06776, 0.02777, -0.01918, -0.87672, -0.67837]
[0.06776, -0.02777, 0.01918, 0.87672, -0.35571]
[0.69619, 0.7811, 0.01918, 0.87672, -0.01102]
[0.01433, -0.18881, 0.00813, 0.23298, -0.08906]
[0.01433, -0.18881, 0.00813, 0.23298, 0.12679]
[-0.94568, 1.84419, 0.00813, 0.23299, -0.01711]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...