Я пытаюсь построить массив, где каждая строка содержит k-mers (k длины нуклеотидных строк) из другой последовательности. Я читал, что у вас не может быть пустых массивов, и мне было трудно попробовать использовать append.
bases = ['A', 'T', 'C', 'G']
self.profile = np.array([])
for x in range(1):
k = self.ksize
kmer = [''.join(p) for p in itertools.product(bases, repeat=k)]
for i in range(0, len(self.motifs)):
for q in range(0, len(kmer)):
if kmer[q] in self.motifs[i]:
self.kmers.append(kmer[q])
self.profile[i] = self.kmers
Ошибка, которую я получаю здесь: "IndexError: индекс 0 выходит за рамки для оси 0 с размером 0"
Я понимаю, что это потому, что я не определял форму массива, но знаю только количество строк, я не знаю, сколько будет столбцов (размер столбца зависит от того, сколько k-mers найденных в каждой последовательности).
Если я попытаюсь сделать его "списком списков":
bases = ['A', 'T', 'C', 'G']
self.profile = list()
for x in range(1):
k = self.ksize
kmer = [''.join(p) for p in itertools.product(bases, repeat=k)]
for i in range(0, len(self.motifs)):
for q in range(0, len(kmer)):
if kmer[q] in self.motifs[i]:
self.kmers.append(kmer[q])
self.profile[i] = self.kmers
Я просто получаю: self.profile [i] = self.kmers IndexError: индекс назначения списка вне диапазона
Есть лучший способ сделать это?
Собирая информацию из комментариев, я думаю, что вы хотите следующее: учитывая список мотивов (в вашем случае, нуклеотидные строки длиной 50 байт), вы хотите, чтобы подпоследовательности (k-mers) длины k, которые появлялись в каждый. Чем больше pythonic способ написать ваш код будет:
bases = ['A', 'T', 'C', 'G']
self.profile = []
k = self.ksize
kmer = [''.join(p) for p in itertools.product(bases, repeat=k)]
for mot in self.motifs:
for km in kmer:
if km in mot:
self.kmers.append(km)
self.profile.append(self.kmers)
Обратите внимание, что в python вам не нужно перебирать индексы, если вы собираетесь использовать их для доступа к спискам, массивам или любым итерабельным; вы можете просто перебирать итерируемый себя. Проверьте zip
и enumerate
для большей гибкости.
Еще одна вещь: обратите внимание, что self.kmer
будет списком, [kmer1, kmer2, kmer4, kmer6]
и т.д. (Т. Е. Ксеры в мотиве), но вы не сможете различать мотивы. Кроме того, self.profile
будет списком списков, содержащих [[kmer1], [kmer1, kmer2], [kmer1, kmer2, kmer4]]
и т.д.
Если вы не заботитесь о self.profile
(потому что вы можете его построить позже), вы можете сделать все с большим пониманием списка:
kmers = [km for mot in motifs for km in kmer if km in mot]
EDIT: две дополнительные вещи
Обратите внимание, что таким образом, kmers
будут иметь повторяющиеся последовательности. Чтобы избежать этого, вы можете либо написать дополнительный чек (if km not in self.kmers
), а, скорее, использовать наборы, чтобы избежать повторения.
Если вам нужен список сортировщиков, разделенных мотивами, вы можете сделать это более простым способом со списком:
self.profile = []
for mot in motifs:
individual_km = [km for km in kmer if km in mot]
self.profile.append(individual_km)
Массивные массивы не очень удобны для динамического роста, как списки и словари python. Если факт, который я прочитал, чтобы произвольно вырастить массивы Numpy, новый массив создается в желаемой форме, а затем копия создается из исходного объекта массива, что не слишком оптимально.
Чтобы достичь результатов, которые вам нужны, мне сначала нужно создать вложенные объекты списка, а затем создать массив Numpy сразу после завершения итераций. Поскольку размер вложенных объектов списка равен, вы можете просто использовать что-то вроде:
my_profile = []
... ваш код цикла...
self.profile = np.array(my_profile)
reange(0, len(kmer))
точно такой же, как иrange(len(kamer))
.self.profile
случае, если массивы, которые выself.profile
вself.profile
, не имеют одинаковую длину, numpy - это не то, что вам нужно: [ stackoverflow.com/questions/3386259/… .