Подсчет элементов в txt — файле с помощью словарей Python

#python #dictionary #count #bioinformatics #contains

Вопрос:

У меня есть следующий текстовый файл (приведен только фрагмент)

      ## DISTANCE : Shortest distance from variant to transcript
## a lot of comments here
    ## STRAND : Strand of the feature (1/-1)
    ## FLAGS : Transcript quality flags
    #Uploaded_variation     Location        Allele  Gene    Feature Feature_type    Consequence     cDNA_position   CDS_position    Protein_position        Amino_acids     Codons  Existing_variation      Extra
    chr1_69270_A/G  chr1:69270      G       ENSG00000186092 ENST00000335137 Transcript      upstream_gene_variant      216     180     60      S       tcA/tcG -       IMPACT=LOW;STRAND=1
    chr1_69270_A/G  chr1:69270      G       ENSG00000186092 ENST00000641515 Transcript      intron_variant      303     243     81      S       tcA/tcG -       IMPACT=LOW;STRAND=1
    chr1_69511_A/G  chr1:69511      G       ENSG00000186092 ENST00000335137 Transcript      upstream_gene_variant        457     421     141     T/A     Aca/Gca -       IMPACT=MODERATE;STRAND=1
 

со многими неизвестными различными номерами ENSG, такими как ENSG00000187583 и т. Д. Количество целых чисел в каждой строке ENSG равно 11.

Я должен посчитать, сколько intron_variant и upstream_gene_variant содержит каждый ген (ENSGxxx). и выведите его в csv-файл.

Для этой цели я использую словарь. я пытался написать этот код, но не был уверен в правильном синтаксисе. Логика должна быть такой: если этих 11 чисел нет в словаре, оно должно быть добавлено со значением 1. Если они уже есть в словаре, значение следует изменить на x 1. В настоящее время у меня есть этот код, но я на самом деле не программист на Python и не уверен в правильном синтаксисе.

     with open(file, 'rt') as f:
        data = f.readlines()
        Count = 0
        d = {}
        for line in data:
            if line[0] == "#":
                output.write(line)
            if line.__contains__('ENSG'): 
                d[line.split('ENSG')[1][0:11]]=1
                if 1 in d:
                    d=1
                else:
                    Count  = 1
 

Есть какие-нибудь предложения?

Спасибо!

Комментарии:

1. В чем именно заключается ваш вопрос об этом коде? Интерпретатор Python сообщит вам, правильный ли синтаксис. Делает ли это то, что вы хотите? Если нет, то что же он делает не так?

2. Это просто работает с приведенным вами примером. 4 {'00000187961': 1, '00000187583': 1} Количество = 4. Это нормально?

Ответ №1:

Можете ли вы попробовать это:

 from collections import Counter

with open('data.txt') as fp:
    ensg = []
    for line in fp:
        idx = line.find('ENSG')
        if not line.startswith('#') and idx != -1:
            ensg.append(line[idx 4:idx 15])
count = Counter(ensg)
 
 >>> count
Counter({'00000187961': 2, '00000187583': 2})
 

Обновить

Мне нужно знать, сколько ENG содержат «intron_variant» и «upstream_gene_variant»

Используйте регулярное выражение для извлечения нужных шаблонов:

 from collections import Counter
import re

PAT_ENSG = r'ENSG(?P<ensg>d{11})'
PAT_VARIANT = r'(?P<variant>intron_variant|upstream_gene_variant)'

PATTERN = re.compile(fr'{PAT_ENSG}.*b{PAT_VARIANT}b')

with open('data.txt') as fp:
    ensg = []
    for line in fp:
        sre = PATTERN.search(line)
        if not line.startswith('#') and sre:
            ensg.append(sre.groups())
    count = Counter(ensg)
 

Выход:

 >>> count
Counter({('00000186092', 'upstream_gene_variant'): 2,
         ('00000186092', 'intron_variant'): 1})
 

Комментарии:

1. Спасибо! но теперь он выводит количество всех идентификаторов ENSG, но нужно знать, сколько ENG содержат «intron_variant» и «upstream_gene_variant».

2. Я предлагаю вам опубликовать ожидаемый результат вашей выборки. Мне будет легче.

3. Спасибо! На самом деле желаемый результат состоял в том, чтобы подсчитать, сколько upstream_gene_variant или intron_variant существует для каждого гена?

4. @пользователь15480777. Я обновил свой ответ. Не могли бы вы проверить мой ответ, пожалуйста?

Ответ №2:

Вот еще одна интерпретация вашего требования:-

Я изменил ваши примерные данные таким образом, чтобы первое значение ENG было ENSG00000187971, чтобы подчеркнуть, как это работает.

 D = {}

with open('eng.txt') as eng:
    for line in eng:
        if not line.startswith('#'):
            t = line.split()
            V = t[6]
            E = t[3]
            if not V in D:
                D[V] = {}
            if not E in D[V]:
                D[V][E] = 1
            else:
                D[V][E]  = 1
print(D)
 

Результатом этого является:-

{‘интрон_вариант’: {‘ENSG00000187971’: 1, ‘ENSG00000187961’: 1}, ‘восходящий поток_гене_вариант’: {‘ENSG00000187583’: 2}}

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

Комментарии:

1. Здравствуйте, я пробовал это, но теперь получаю следующее: «Ошибка индекса: индекс списка вне диапазона» . Я использую Python 3

2. Ваши данные должны отличаться по содержанию или структуре от образца, который вы первоначально опубликовали

3. Здравствуйте, я обновил образец. Существуют различия в заголовке

4. Это будет работать с вашими данными. Вы только что добавили строки комментариев в свой образец, для которого этот код учитывает