Как получить данные из базы данных с неправильным форматированием в Python? - PullRequest
0 голосов
/ 09 мая 2019

Я работаю над кодом для расчета различных термодинамических свойств данного набора молекул.Для этого мне нужно включить 9 коэффициентов в систему уравнений, чтобы получить нужные значения.Эти коэффициенты, которые варьируются от молекулы к молекуле, извлекаются из базы данных NASA Thermobuild, которая имеет следующий формат:

C2Cl4 Тетрахлорэтилен HF298 = -5,034 ккал Burcat G3B3
3 T05 / 08 C 2.00CL 4.000,00 0,00 0,00 0 165,8322000 -21064.348 50.000 200.000 7 -2,0 -1,0 0,0 1,0 2,0 3,0 0,0 19563,551 -5,821898980D + 03 4,158580080D + 02-7.790140830D + 00 1,615966138D-01 -6,791370520D-04 1,5984318758-06-1,55688D-09 0.000000000D + 00-6.205198010D + 03 5.774956220D + 01 200.000 1000.000 7 -2,0 -1,0 0,0 1,0 2,0 4,0 0,0 19563,551

4,940446670D + 04 -1,030763621D + 03 1,098508036D+01 1.645945662D-02-2.178412229D-05 1.410593520D-08-3.663931630D-12 0.000000000D + 00 -3.353235260D + 02-2.878634227D + 01 1000.000 6000.000 7 -2.0 -1.00.0 1.0 2.0 3.0 4.0 0.0 19563.551 -3.067008915D + 05-1.128336557D + 03 1.681089243D + 01-3.159107946D-04 6.850908950D-08 -7.749796920D-12 3.556100470D-16 0.000000000D + 00-1.944193938D + 03-5,966Д + 01

ТКонкретные числа, которые мне нужны для расчетов, выделены жирным шрифтом.

(альтернативно, в виде кодового блока, так что он немного точнее и ближе к фактическому расположению в файле базы данных .txt)

C2Cl4 Tetrachloroethylene  HF298=-5.034 kcal Burcat G3B3                         
3 T05/08 C   2.00CL  4.00    0.00    0.00    0.00 0  165.8322000     -21064.348
 50.000   200.000 7 -2.0 -1.0  0.0  1.0  2.0  3.0  4.0  0.0        19563.551
-5.821898980D+03 4.158580080D+02-7.790140830D+00 1.615966138D-01-6.791370520D-04
 1.598431875D-06-1.556882412D-09 0.000000000D+00-6.205198010D+03 5.774956220D+01
 200.000  1000.000 7 -2.0 -1.0  0.0  1.0  2.0  3.0  4.0  0.0        19563.551
 4.940446670D+04-1.030763621D+03 1.098508036D+01 1.645945662D-02-2.178412229D-05
 1.410593520D-08-3.663931630D-12 0.000000000D+00-3.353235260D+02-2.878634227D+01
 1000.000  6000.000 7 -2.0 -1.0  0.0  1.0  2.0  3.0  4.0  0.0        19563.551
-3.067008915D+05-1.128336557D+03 1.681089243D+01-3.159107946D-04 6.850908950D-08
-7.749796920D-12 3.556100470D-16 0.000000000D+00-1.944193938D+03-5.966771040D+01

В базе данных есть сотни молекул, но мне нужны коэффициенты только для примерно 50, мне нужна функция, которая будет проходить, найти нужные мне молекулярные виды из заранее написанного списка, затем выбрать каждый коэффициент иверните их, чтобы я мог использовать их в своих вычислениях (и преобразовать «D + 0% N» в «E + 0% N» - я не уверен, почему в этой базе данных используются D вместо E для представления научной записи).

Я совсем не знаком с SQL, поэтому я просто сосредоточился на основных функциях поиска Python.Пока что у меня есть следующее:

import pandas as pd
import csv
import math
import numpy as np
species_list=[]
species=pd.read_table('Species list.txt') #list of molecular species I need coefficients for
species_temp=species['Species']
for i in range(len(species_temp)):
    species_list.append(species_temp[i])
with open('NEWNASA.TXT','rt') as database: #loads massive coefficient database
    for species_name in species_list:
        species_name=species_name+" " #to avoid returning ionic forms
            for line in database:
                if species_name in line:
                print line #test to see if it's working

Однако, а) это перестает работать после нахождения первого молекулярного вида, и б) я все еще не уверен, как сказать коду, чтобы найти конкретные коэффициентыМне нужно для расчетов.Я полагаю, что это будет включать регулярные выражения (с которыми у меня тоже нет особого опыта) и индексацию, но это насколько я понял.Любые указатели или предложения будут высоко оценены!

Спасибо!

Ответы [ 2 ]

1 голос
/ 16 мая 2019

Я решу вопрос извлечения нужных данных из записи в вашей текстовой базе данных.

Как только вы найдете интересующую вас запись (if species_name in line:), вам нужно перейти к седьмому.и восьмой строки этой записи и извлечь коэффициенты.

Формат записи указывает, что каждая строка имеет длину 80 символов, а каждое интересующее вас число имеет длину 16 символов.Поэтому разделите седьмую и восьмую строки на пять равных частей (Split a string to even sized chunks) и сделайте из них числа с плавающей запятой

Настройка:

import io

r = '''C2Cl4 Tetrachloroethylene  HF298=-5.034 kcal Burcat G3B3                         
3 T05/08 C   2.00CL  4.00    0.00    0.00    0.00 0  165.8322000     -21064.348
 50.000   200.000 7 -2.0 -1.0  0.0  1.0  2.0  3.0  4.0  0.0        19563.551
-5.821898980D+03 4.158580080D+02-7.790140830D+00 1.615966138D-01-6.791370520D-04
 1.598431875D-06-1.556882412D-09 0.000000000D+00-6.205198010D+03 5.774956220D+01
 200.000  1000.000 7 -2.0 -1.0  0.0  1.0  2.0  3.0  4.0  0.0        19563.551
 4.940446670D+04-1.030763621D+03 1.098508036D+01 1.645945662D-02-2.178412229D-05
 1.410593520D-08-3.663931630D-12 0.000000000D+00-3.353235260D+02-2.878634227D+01
 1000.000  6000.000 7 -2.0 -1.0  0.0  1.0  2.0  3.0  4.0  0.0        19563.551
-3.067008915D+05-1.128336557D+03 1.681089243D+01-3.159107946D-04 6.850908950D-08
-7.749796920D-12 3.556100470D-16 0.000000000D+00-1.944193938D+03-5.966771040D+01'''

db = io.StringIO(r)
species_name = 'Tetrachloroethylene'

Процесс:

def get_coefficients(line):
    '''Split line into 5 floats.

    line has five 16 character numbers.
    '''
    #coefficients = [line[i:i+16] for i in range(0,len(line),16)]
    coefficients = [line[i:i+16] for i in range(0,80,16)] # 80 cols/line
    coefficients = map(lambda q: q.replace('D','E'), coefficients)
    coefficients = [float(thing) for thing in coefficients]
    return coefficients

for line in db:
    if species_name in line:    # first lne of the record
        # skip to the seventh line of the record
        for _ in range(6):
            line = next(db)
        coefficients_1 = get_coefficients(line)
        print(coefficients_1)
        # skip to the eighth line of the record
        line = next(db)
        coefficients_2 = get_coefficients(line)
        print(coefficients_2)

Вам необходимо решить проблему, поднятую @FMc.В настоящее время ваш код перебирает имена в списке, и для каждого имени вы перебираете весь файл базы данных, ища имя.Чтобы продолжить поиск следующего имени, вам нужно снова начать поиск начала файла, установив указатель файла на начало, database.seek(0).

Это будет очень неэффективно.Как указано @Fmc, вам нужно перебрать каждую строку базы данных и посмотреть, содержит ли она одно из названий ваших видов.Чтобы улучшить это, species_list должен быть set .

species_list = {'Tetrachloroethylene', 'Bar', 'Foo'}

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

  • в вашей записи примера,Первая строка содержит формулу вида и название.Таблица формата записи базы данных предполагает, что первая строка содержит имя или формулы.
  • Формат записи базы данных говорит, что имя или формула находятся в первых 17 символах первой строки, но имя в вашем примере заканчивается 26-м символом.

ЕслиПервая строка каждой записи - это вариант вашего примера и определения формата записи, может быть, вы можете попробовать что-то вроде:

for line in db:
    stuff = line.split()
    # blank lines in db?
    if len(stuff) > 0 and stuff[0] in species_list:
        # go to lines seven and eight and get coeffs
    elif len(stuff) > 1 and stuff[1] in species_list:
        # go to lines seven and eight and get coeffs
    else:
        continue
1 голос
/ 09 мая 2019

Открытый файл (database) является одноразовым итератором. Вы не можете пройти его несколько раз. Решение состоит в том, чтобы поменять местами циклы for или загрузить все строки файла в список, если файл не слишком большой.

for line in database:
    for species_name in species_list:
        species_name = species_name + " "
        if species_name in line:
            print line
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...