Сделайте что-нибудь, чтобы строка и следующие строки, пока символ не ударил

У меня есть данные, которые настроены следующим образом:

//Name_1   *   *
>a       xyzxyzyxyzyxzzxy
>b       xyxyxyzxyyxzyxyz
>c       xyzyxzyxyzyxyzxy
//Name_2  
>a       xyzxyzyxyzxzyxyx
>b       zxyzxyzxyyzxyxzx
>c       zxyzxyzxyxyzyzxy
//Name_3  *          *
>a       xyzxyzyxyzxzyxyz
>b       zxyzxyzxzyyzyxyx
>c       zxyzxyzxyxyzyzxy
...

//- строка относится к идентификатору для следующей группы последовательностей, пока не будет достигнута следующая //- строка. Я работал над написанием программы, которая считывает положение звездочки и печатает символы в заданной позиции для последовательностей. Чтобы упростить для себя вещи, я работал над подмножеством своих данных, содержащим только одну группу последовательностей, например:

//Name_1   *   *
>a       xyzxyzyxyzyxzzxy
>b       xyxyxyzxyyxzyxyz
>c       xyzyxzyxyzyxyzxy

Моя программа делает то, что я хочу на этом подмножестве.

import sys
import csv

datafile = open(sys.argv[1], 'r')

outfile = open(sys.argv[1]+"_FGT_Data", 'w')
csv_out = csv.writer(outfile, delimiter=',')

csv_out.writerow(['Locus', 'Individual', 'Nucleotide', 'Position'])

with (datafile) as searchfile:
    var_line = [line for line in searchfile  if '*' in line]
    LocusID = [line[2:13].strip() for line in var_line]
    poslist = [i for line in var_line for i, x in enumerate(line) if x =='*']

datafile = open(sys.argv[1], 'r')


with (datafile) as getsnps:
    lines = [line for line in getsnps.readlines() if line.startswith('>')]
    for pos in poslist:
        for line in lines:
            snp = line[pos]

            individual = line[0:7]
            indistr = individual.strip()
            csv_out.writerow((LocusID[0], indistr, line[pos], str(pos)))


datafile.close()
outfile.close()

Однако сейчас я пытаюсь изменить его для работы с полным набором данных. У меня проблемы с поиском способа перебора данных правильным способом. Мне нужно выполнить поиск в файле, и когда будет достигнута строка, содержащая '', мне нужно сделать, как в приведенном выше коде, последовательности, соответствующие данной строке, а затем перейти к следующей строке, содержащей ''. Нужно ли разделять мои данные по //- строкам или каков наилучший подход?

Я загрузил образец своих данных в dropbox: Data_Sample.txt содержит несколько групп и является видом данных, над которым я пытаюсь заставить программу работать. Data_One_Group.txt содержит только одну группу, и это данные, с которыми я получил программу для работы до сих пор.

https://www.dropbox.com/sh/3j4i04s2rg6b63h/AADkWG3OcsutTiSsyTl8L2Vda?dl=0

--------РЕДАКТИРОВАТЬ---------

Я пытаюсь реализовать предложение @Julien Spronck ниже. Однако у меня возникли проблемы при обработке полученного блока. Как бы я мог искать через строку блока для строки. Например, почему ниже не работает, как задумано? Он просто печатает звездочку, а не саму строку.

block =''
with open('onelocus.txt', 'r') as searchfile:
    for line in searchfile:
        if line.startswith('//'):
            #print line
            if block:
                for line in block:
                    if '*' in line:
                        print line

            block = line
        else:
            block += line

--------- РЕДАКТИРОВАТЬ 2----------

Я все ближе. Я понимаю тот факт, что мне нужно разбить строку на строку, чтобы иметь возможность искать их. Приведенное ниже описание относится к одной группе, но когда я пытаюсь выполнить итерации для нескольких групп, выводится информация только для первой группы. Но делает это для столько групп, сколько есть. Я пытался очистить LocusID и poslist перед следующей итерацией, но это не похоже на решение.

block =''
with (datafile) as searchfile:
    for line in searchfile:
        if line.startswith('//'):
            if block:
                    var_line = [line for line in block.splitlines()  if '*' in line]  
                    LocusID = [line[2:13].strip() for line in var_line]
                    print LocusID
                    poslist = [i for line in var_line for i, x in enumerate(line) if x == '*'] 
                    print poslist



            block = line
        else:
            block += line

3 ответа

Разве вы не можете сделать что-то вроде:

block =''
with open(filename, 'r') as fil:
    for line in fil:
        if line.startswith('//'):
            if block:
                do_something_with(block)
            block = line
        else:
            block += line
if block:
    do_something_with(block)

В этом коде я просто добавляю строки файла в переменную block, Как только я нахожу строку, которая начинается с //Я обрабатываю предыдущий блок и повторно инициализирую блок для следующей итерации.

Последние две строки позаботятся об обработке последнего блока, который не был бы обработан в противном случае.

do_something_with(block) может быть что-то вроде этого:

def do_something_with(block):

    lines = block.splitlines()

    j = 0
    first_line = lines[j]
    while first_line.strip() == '':
        j += 1
        first_line = lines[j]

    pos = []
    position = first_line.find('*')
    while position != -1:
        pos.append(position)
        position = first_line.find('*', position+1)

    for k, line in enumerate(lines):
        if k > j:
            for p in pos:
                print line[p], 
            print

## prints
## z y
## x z
## z y

Я создал способ заставить эту работу работать с предоставленными вами данными. Вы должны запустить его с двумя расположениями файлов, 1 должен быть ваш input.txt и 2 должен быть ваш output.csv

объяснение

  • Сначала мы создаем словарь с локусом в качестве ключа и последовательности в качестве значений.
  • Перебираем этот словарь и получаем * места в локусе и добавить их в список indexes,
  • Мы перебираем значения, принадлежащие этому ключу, и извлекаем последовательность
  • за одну итерацию мы повторяем indexes так что мы собираем snps.
  • за каждую итерацию мы добавляем наш CSV-файл.
  • Мы очищаем список индексов, чтобы перейти к следующему ключу.

Иметь ввиду

  • Этот метод сильно зависит от количества пробелов в вашем файле input.txt.

  • Вы должны знать, что это не будет самый быстрый способ сделать это. но это сделано.

Я надеюсь, что это помогло, если у вас есть какие-либо вопросы, не стесняйтесь их задавать, и если у меня будет время, я с радостью постараюсь ответить на них.


скрипт

import sys
import csv

sequences = []
dic = {}
indexes = []
datafile = sys.argv[1]
outfile = sys.argv[2]

with open(datafile,'r') as snp_file:
    lines = snp_file.readlines()
    for i in range(0,len(lines)):
        if lines[i].startswith("//"):
            dic[lines[i].rstrip()] = sequences
            del sequences[:]
        if lines[i].startswith(">"):
            sequences.append(lines[i].rstrip())

for key in dic:
    locus = key.split(" ")[0].replace("//","")
    for i, x in enumerate(key):
        if x == '*':
            indexes.append(i-11)

    for sequence in dic[key]:
        seq = sequence.split("    ")[1]
        seq_id = sequence.split("    ")[0].replace(">","")
        for z in indexes:
            position = z+1
            nucleotide = seq[z]

            with open(outfile,'a')as handle:
                csv_out = csv.writer(handle, delimiter=',')
                csv_out.writerow([locus,seq_id,position,nucleotide])
    del indexes[:]

input.txt

//Locus_1  *                    * 
>Safr01    AATCCGTTTTAAACCAGNTCYAT
>Safr02    TTAATCCGTTTTAAACCAGNTCY
//Locus_2      *             *    
>Safr01    AATCCGTTTTAAACCAGNTCYAT
>Safr02    TTAATCCGTTTTAAACCAGNTCY

output.csv

Locus_1,Safr01,1,A
Locus_1,Safr01,22,A
Locus_1,Safr02,1,T
Locus_1,Safr02,22,C
Locus_2,Safr01,5,C
Locus_2,Safr01,19,T
Locus_2,Safr02,5,T
Locus_2,Safr02,19,G

Вот как я решил проблему:

def do_something_with(block):

lines = block.splitlines()
for line in lines:
    if '*' in line:
        hit = line
        LocusID = hit[2:13].strip()

        for i, x in enumerate(hit):
            if x=='*':
                poslist.append(i)
for pos in poslist:
    for line in lines:
        if line.startswith('>'):
            individual = line[0:7].strip()
            snp = line[pos]
            print LocusID, individual, snp, pos,
            csv_out.writerow((LocusID, individual, snp, pos))   

with (datafile) as searchfile:
    for line in searchfile:
        if line.startswith('//'):
            if block:
                do_something_with(block)
                poslist = list()
            block = line
        else:
            block += line
if block:
    do_something_with(block)
Другие вопросы по тегам