Разобрать строку из нескольких столбцов, используя python
Я пытаюсь извлечь данные из текстового вывода программы хеминформатики под названием NWChem
Я уже выделил ту часть вывода, которая мне интересна (колебательные моды), вот строка, которую я извлек:
s = ''' 1 2 3 4 5 6
P.Frequency -0.00 0.00 0.00 0.00 0.00 0.00
1 -0.23581 0.00000 0.00000 0.00000 0.01800 -0.04639
2 0.00000 0.25004 0.00000 0.00000 0.00000 0.00000
3 -0.00000 0.00000 0.00000 0.00000 -0.21968 -0.08522
4 -0.23425 0.00000 0.00000 0.00000 -0.14541 0.37483
5 0.00000 0.00000 0.99611 0.00000 0.00000 0.00000
6 0.00192 0.00000 0.00000 0.00000 -0.42262 0.43789
7 -0.23425 0.00000 0.00000 0.00000 -0.14541 0.37483
8 0.00000 0.00000 0.00000 0.99611 0.00000 0.00000
9 -0.00193 0.00000 0.00000 0.00000 -0.01674 -0.60834
7 8 9
P.Frequency 1583.30 3661.06 3772.30
1 -0.00000 -0.00000 0.06664
2 0.00000 0.00000 0.00000
3 -0.06754 0.04934 0.00000
4 0.41551 0.56874 -0.52878
5 0.00000 0.00000 0.00000
6 0.53597 -0.39157 0.42577
7 -0.41551 -0.56874 -0.52878
8 0.00000 0.00000 0.00000
9 0.53597 -0.39157 -0.42577'''
Сначала я разбил данные на строки с помощью регулярного выражения.
import re
p = re.compile('\n + +(?=[\d| ]+\n\n P.Frequency +)')
d = re.split(p, s)
print(d[0])
1 2 3 4 5 6
P.Frequency -0.00 0.00 0.00 0.00 0.00 0.00
1 -0.23581 0.00000 0.00000 0.00000 0.01800 -0.04639
2 0.00000 0.25004 0.00000 0.00000 0.00000 0.00000
3 -0.00000 0.00000 0.00000 0.00000 -0.21968 -0.08522
4 -0.23425 0.00000 0.00000 0.00000 -0.14541 0.37483
5 0.00000 0.00000 0.99611 0.00000 0.00000 0.00000
6 0.00192 0.00000 0.00000 0.00000 -0.42262 0.43789
7 -0.23425 0.00000 0.00000 0.00000 -0.14541 0.37483
8 0.00000 0.00000 0.00000 0.99611 0.00000 0.00000
9 -0.00193 0.00000 0.00000 0.00000 -0.01674 -0.60834
Однако я не могу понять, как я могу извлечь колебательные моды, которые представлены вертикально. Я хотел бы легко получить доступ к каждому колебательному режиму в массиве массива или, может быть, в массиве. как это:
[[-0.00, -0.23581, 0.0000, ..., -0.00193],
[0.00, 0.00000, ..., 0.00000],
...
[3772.30, 0.06664, ..., 0.0000, --0.42577]]
2 ответа
С 2 np.genfromtxt
читает, я могу загрузить ваш файл данных в 2 массива и объединить их в один массив 9x9:
In [134]: rows1 = np.genfromtxt('stack30874236.txt',names=None,skip_header=4,skip_footer=10)
In [135]: rows2 =np.genfromtxt('stack30874236.txt',names=None,skip_header=17)
In [137]: rows=np.concatenate([rows1[:,1:],rows2[:,1:]],axis=1)
In [138]: rows
Out[138]:
array([[-0.23581, 0. , 0. , 0. , 0.018 , -0.04639, -0. , -0. , 0.06664],
[ 0. , 0.25004, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
...
[-0.00193, 0. , 0. , 0. , -0.01674, -0.60834, 0.53597, -0.39157, -0.42577]])
In [139]: rows.T
Out[139]:
array([[-0.23581, 0. , -0. , -0.23425, 0. , 0.00192, -0.23425, 0. , -0.00193],
[ 0. , 0.25004, 0. , 0. , 0. , 0. ,
...
[ 0.06664, 0. , 0. , -0.52878, 0. , 0.42577, -0.52878, 0. , -0.42577]])
Я должен был выбрать пропустить значения верхнего / нижнего колонтитула, чтобы соответствовать файлу данных. Вывод их с помощью кода потребует еще немного работы.
Как предположил hpaulj, функция numpy genfromtxt
, очень удобно анализировать такие строки, однако, так как я использую python3, мне нужно преобразовать мою строку в поток байтов, чтобы передать ее этой функции.
Вот код, который добился цели:
import numpy as np
from io import BytesIO
i = 0
for row in d:
values = np.genfromtxt(BytesIO(row.encode(encoding='UTF-8')), skip_header=1).transpose()[1:]
if i == 0:
data = values
else:
data = np.concatenate((data, values))
i += 1