Перебор парных строк и подсчет с использованием python

#python #for-loop #split #iterator #pattern-matching

#питон #для цикла #сплит #итератор #сопоставление с образцом

Вопрос:

У меня есть текстовый файл, который выглядит как:

 >MN00153:75:000H37WNG:1:11102:13823:1502
CCTGCGTTGAAGTGGCTTACTTGCACCTTATGCTACCGTGACCTGCGAATCCAGTCTCATCGTGACCATTCAGGACCAGTGGCAAGAGATCGGAAGAGCACACGTCTGAACTCCAGTCACCGCTCATTATCTCGTATGCCGTCTTCTGCTT
CASP3_fw1_rc : CCATTCAGGACCAGTGGCAAG - The position is 66
CASP3_fw2 : CCTGCGTTGAAGTGGCTTACT - The position is 1
Distance is 44

>MN00153:75:000H37WNG:1:11102:13823:1504
CCTGCGTTGAAGTGGCTTACTTGCACCTTATGCTACCGTGACCTGCGAATCCAGTCTCATCGTGACCATTCAGGACCAGTGGCAAGAGATCGGAAGAGCACACGTCTGAACTCCAGTCACCGCTCATTATCTCGTATGCCGTCTTCTGCTT
CASP3_fw1_rc : CCATTCAGGACCAGTGGCAAG - The position is 66
CASP3_fw2 : CCTGCGTTGAAGTGGCTTACT - The position is 1
Distance is 44

>MN00153:75:000H37WNG:1:11102:13823:1506
CCTGCGTTGAAGTGGCTTACTTGCACCTTATGCTACCGTGACCTGCGAATCCAGTCTCATCGTGACCATTCAGGACCAGTGGCAAGAGATCGGAAGAGCACACGTCTGAACTCCAGTCACCGCTCATTATCTCGTATGCCGTCTTCTGCTT
CASP3_fw1_rc : CCATTCAGGACCAGTGGCAAG - The position is 66
CASP3_fw2_rc : CCTGCGTTGAAGTGGCTTACT - The position is 1
Distance is 44

>MN00153:75:000H37WNG:1:11102:13823:1508
CCTGCGTTGAAGTGGCTTACTTGCACCTTATGCTACCGTGACCTGCGAATCCAGTCTCATCGTGACCATTCAGGACCAGTGGCAAGAGATCGGAAGAGCACACGTCTGAACTCCAGTCACCGCTCATTATCTCGTATGCCGTCTTCTGCTT
CASP3_fw1_rc : CCATTCAGGACCAGTGGCAAG - The position is 66
EIF2_fw2 : CCTGCGTTGAAGTGGCTTACT - The position is 1
Distance is 44
 

Меня интересуют строки 3 и 4 каждого сегмента (начинаются с ‘>’). Я хочу посчитать 1, если строка 3 и строка 4 — это CASP3 (независимо от того, что будет потом). таким образом, результат должен быть

 3
 

Потому что первый, второй и третий сегменты имеют пару CASP3 в строках 3 и 4 каждого сегмента (кроме последнего).

Спасибо

Ответ №1:

Если ваш файл не слишком велик, вы можете использовать .readlines функцию для получения list строк следующим образом:

 with open('filename.txt', 'r') as f:
    lines = f.readlines()
 

затем используйте enumerate и str методы следующим образом:

 cnt = 0
for inx, line in enumerate(lines):
    if line.startswith('>') and lines[inx 2].startswith('CASP3') and lines[inx 3].startswith('CASP3'):
        cnt  = 1
print(cnt)
 

Мое решение требует , чтобы после последней строки было не менее 3 строк , начинающихся с > .

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

1. Спасибо за ваше отличное решение. Можно ли было бы использовать ваш код также таким образом, чтобы if [inx 2] и [inx 3] не были похожи (только часть перед первой _ ), а затем получить счетчик для этого?

Ответ №2:

Без чтения всего файла в память:

 def startswith_casp(iterator):
    # grab the next four lines of your file
    chunk = [line for _, line in zip(range(3), iterator)]
    # use a slice here to avoid index errors
    return all(c.startswith('CASP3') for c in chunk[1:3])
        
with open('yourfile.txt') as fh:
    count = 0

    for line in fh:
        if not line.strip():
            continue
        elif line.startswith('>'):
            # Function returns a boolean, so True will add 1 while False adds 0
            count  = startswith_casp(fh)
        else:
            continue

print(count)
 

Ответ №3:

Здесь я split использую by nn , чтобы получить «ведра», затем by n , чтобы получить строки внутри каждого ведра, затем проверяю 3-ю ( [2] ) и 4-ю ( [3] ) строки в каждом ведре на наличие шаблона:

 with open('genes.txt') as file:
    data = file.read()

by_bucket = [i.split('n') for i in data.split('nn')]

count = 0
for bucket in by_bucket:
    count  = (bucket[2].startswith('CASP3') and bucket[3].startswith('CASP3'))

print(count)
 

Ответ №4:

Вероятно, это помогло бы, если бы вы объяснили, что вы уже пробовали. Это, как говорится, вот общий подход:

  • Используйте этот .split() метод для разделения на любые символы, которые вы хотите. В результате вы получите список, в котором каждая запись будет представлять собой одно ведро.
  • Просмотрите этот список с for VariableName in ExampleList: помощью, чтобы проверить каждое ведро самостоятельно.
  • При желании вы можете проверить, является ли первая запись a > , или если вы правильно выполнили разделение, возможно, вам это и не понадобится.
  • Разделите каждое ведро в другой список , где каждая запись занимает одну строку , используя bucket.splitlines() .
  • Затем проверьте, соответствуют ли первые символы 3-й и 4-й записи в этом списке CASP3 , проверив, являются ли string[2][:5]=="CASP3" (для третьей строки) и string[3][:5]=="CASP3" (для четвертой строки) истинными.
  • Добавьте к функции еще один счетчик, который увеличивается на 1 всякий раз, когда допустимо одно ведро.
  • верните этот счетчик.

Если у вас есть дополнительные вопросы, не стесняйтесь задавать их.

Вот пример, который принимает строку и возвращает нужное вам значение:

 def getValue(string):
    counter=0
    splitList=string.split("nn")
    for bucket in splitList:
        bucket=bucket.splitlines()
        if bucket[2][:5]=="CASP3" and bucket[3][:5]=="CASP3":
            counter =1
return counter
 

Обратите внимание, что эта функция зависит от того, что сегменты разделяются пустой новой строкой, но вы также можете изменить это, чтобы отделить любые другие символы.

Ответ №5:

Мое решение заключается в чтении file.txt в словарь текстовых разделов (где раздел занимает промежуток между двумя символами больше, чем (например, ‘>’), что затем позволяет вам легко выполнять некоторые сравнения.

 file_path = './file.txt'
keyword="CASP3"
section_ID = 0
count = 0
all_sections = {}

with open(file_path,'r') as f:
    for line in f:
        if line.startswith(">"):
            if line not in all_sections:
                section_ID  = 1
                all_sections[section_ID] = {}
                all_sections[section_ID]['entries'] = []
        all_sections[section_ID]['entries'].append(line)

for sec_id in all_sections:
    if all_sections[sec_id]['entries'][2].startswith(keyword) and all_sections[sec_id]['entries'][3].startswith(keyword):
        count =1
print('count : ', count)
 

вывод с использованием вашего файла будет :

количество: 3