Прочитать в записи несколько строк из файла во вложенный словарь в Python - PullRequest
0 голосов
/ 17 октября 2019

Это на практике вложенный словарь, или массив словарей, список словарей и т. Д. Структура данных лучше всего описывается как массив struct / class в C / C ++, и каждая структура имеет несколько членов. Задача для меня:
1). В начале каждой записи есть строка " Sample Name " в качестве разделителя, за которой следуют несколько членов;
2). 6 членов записи в каждом ряду разделяются двоеточием ":";
3). как читать несколько строк (вместо нескольких полей одной и той же строки, что проще для разбора) в элемент записи;
4). Разделителю record не может предшествовать пустая строка.
Я поместил выборочный ввод и ожидаемый вывод для тестирования.
Пример: input.txt


Sample Name: CanNAM1_192
SNPs                         : 5392
MNPs                         : 0
Insertions                   : 248
Deletions                    : 359
Phased Genotypes             : 8.8% (2349/26565)
MNP Het/Hom ratio            : - (0/0)

Sample Name: CanNAM2_195
SNPs                         : 5107
MNPs                         : 0
Insertions                   : 224
Deletions                    : 351
Phased Genotypes             : 8.9% (2375/26560)
MNP Het/Hom ratio            : - (0/0)

Sample Name: CanNAM3_196
SNPs                         : 4926
MNPs                         : 0
Insertions                   : 202
Deletions                    : 332
Phased Genotypes             : 8.0% (2138/26582)
MNP Het/Hom ratio            : - (0/0)

В awk есть разделитель REC REC и разделитель FIELD FS, который можно установить в начале, но, насколько мне известно, такой функции в python нет.

Output.tab:

CanNAM1_192  5392  0  248  359  8.8%  - 
CanNAM2_195  5107  0  224  351  8.9%  - 
CanNAM3_196  4926  0  202  332  8.0%  - 

Пробовал поискать пример кода для моего дела, как этот один , этот

import sys

filename=sys.argv[1]

Dictn = {}

with open(filename, 'r') as fh:
    for line in fh:
        while True:
            if line.startswith('Sample Name'):
                nameLine = line.strip()
                ID = nameLine.split(':')
            else:
                line2 = next(fh).strip()
                line2 = line2.split(':')
                print (line2[0], line2[1]) # For debugging to see the parsing result
                line3 = next(fh).strip().split(':')
                line4 = next(fh).strip().split(':')
                line5 = next(fh).strip().split(':')
                line6 = next(fh).strip().split(':')
                line7 = next(fh).strip().split(':')
                Dictn.update({
                            ID[1]: {
                                line2[0]: line2[1],
                                line3[0]: line3[1],
                                line4[0]: line4[1],
                                line5[0]: line5[1],
                                line6[0]: line6[1],
                                line7[0]: line7[1],
                                }
                             })
                break
print(Dictn)

Dictn.get('CanNAM1_192')
# {CanNAM1_192:{ {'SNPs' : '5392'}, {'MNPs' : '0'}, {'Insertions' : '248'}, {'Deletions' : '359'}, {'Phased Genotypes' : '8.8%'}, {'MNP Het/Hom ratio' : '-'} }}

Я застрял при разборе каждогозапись, читая 7 строк за раз, затем нажмите / обновите запись в словаре. Не хорошо в Python, и я действительно ценю любую помощь!

Ответы [ 2 ]

1 голос
/ 17 октября 2019
data = {}
with open("data.txt",'r') as fh:
    for line in fh.readlines(): #read in multiple lines
        if len(line.strip())==0:
            continue

        if line.startswith('Sample Name'):
            nameLine = line.strip()
            name = nameLine.split(": ")[1]
            data[name] = {}
        else:
            splitLine = line.split(":")
            variableName = splitLine[0].strip()
            value = splitLine[1].strip()
            data[name][variableName] = value

print(data)
  1. Убедитесь, что строка, которую вы читаете, не пуста. Если вы удалите все пустое пространство из пустой строки, вы получите строку с нулевой длиной. Мы просто проверяем это.
  2. Если строка начинается с Sample Name, мы знаем, что идентификатор будет идти после двоеточия и пробела. Мы можем разделить по этим персонажам. Идентификатор будет второй частью разделенной линии, и поэтому мы просто получим элемент по индексу 1.
  3. Отслеживание текущего идентификатора в переменной (я называю это name). Создайте пустую вложенную словарную запись для этого идентификатора.
  4. Если строка не является строкой идентификатора, то это должна быть строка данных, связанная с последним введенным идентификатором.
  5. Получим строку, разделим ее на :. Имя переменной будет слева, первый элемент, а значение будет справа, поэтому второй элемент. Убедитесь, что мы удалили все лишние пробелы с обеих сторон.
  6. Добавьте пару переменных и значений в словарную запись для идентификатора.
0 голосов
/ 20 октября 2019

Потратил больше времени на вопрос и получил решение, которое кажется НЕ"pythonic", так как мой код, обрабатывающий первую "запись" (8 строк данных, включая пустую строку внизу), является излишнимиз остальных.

import itertools
data = {}
with open("vcfstats.txt", 'r') as f:
    for line in f:
        if line.strip():                #Non blank line
            if line.startswith('Sample Name'):
                nameLine = line.strip()
                name = nameLine.split(": ")[1].strip()
                data[name] = {}
            else:
                splitLine = line.split(": ")
                variableName = splitLine[0].strip()
                values = splitLine[1].strip().split(" ")
                data[name][variableName] = values[0]        #Only take the first item as value
        else:
             continue

    for line in itertools.islice(f, 8):
        lines = (line.rstrip() for line in f)          # including blank lines
        lines = list(line for line in lines if line)   # skip blank lines

        for line in lines:
            if line.startswith('Sample Name'):
                nameLine = line.strip()
                name = nameLine.split(": ")[1].strip()
                data[name] = {}
            else:
                splitLine = line.split(": ")
                variableName = splitLine[0].strip()
                values = splitLine[1].strip().split(" ")
                data[name][variableName] = values[0]        #Only take the first item as value

Что я пропустил? Большое спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...