Сделайте что-нибудь, чтобы строка и следующие строки, пока символ не ударил
У меня есть данные, которые настроены следующим образом:
//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)