使用 for 循环构建 NumPy 数组(列表列表?)

Build NumPy Array with for loop (list of lists?)

我正在尝试构建一个数组,其中每一行都包含来自不同序列的 k-mers(k 长度核苷酸串)。我一直在读到你不能真正拥有空数组,我很难尝试使用追加。

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: index 0 is out of bounds for axis 0 with size 0"

我意识到这是因为我没有指定数组的形状,但我只知道会有多少行,我不知道会有多少列(列的大小取决于如何在每个序列中发现许多 k-mers)。

如果我尝试将其设为 'list of lists':

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: 列表赋值索引超出范围

有更好的方法吗?

Numpy 数组不能像 python 列表和字典那样动态增长。如果事实上,上次我读到,要任意增长 Numpy 数组,创建一个新数组到所需的形状,然后从原始数组对象制作一个副本,这不是最优的。

为了达到您想要的结果,我必须先创建一个嵌套列表对象,然后在迭代完成后一次性创建所有 Numpy 数组。只要嵌套列表对象的大小相等,您就可以使用类似的东西:

my_profile = []

... 你的循环代码 ...

self.profile = np.array(my_profile)

从评论中收集信息,我想你想要的是以下内容:给定一个基序列表(在你的例子中,核苷酸串每个 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 中,如果您只打算使用它来访问列表、数组或任何可迭代对象,则无需遍历索引;你可以循环迭代本身。检查 zipenumerate 以获得更大的灵活性。

最后一件事:请注意 self.kmer 将是一个包含 [kmer1, kmer2, kmer4, kmer6] 等的列表(即您的主题中的 kmers),但您无法区分主题.此外,self.profile 将是包含 [[kmer1], [kmer1, kmer2], [kmer1, kmer2, kmer4]] 的列表列表,依此类推。

如果你不关心self.profile(因为你可以稍后实际构建它),你可以用大列表理解来做任何事情:

kmers = [km for mot in motifs for km in kmer if km in mot]

编辑:另外两件事

注意这样,kmers会有重复的序列。为避免这种情况,您可以写一个额外的 cheack (if km not in self.kmers),或者使用 sets,以避免重复。

如果您想要按主题分隔的 kmers 列表,您可以使用列表理解以更简单的方式完成:

self.profile = [] 
for mot in motifs:
    individual_km = [km for km in kmer if km in mot]
    self.profile.append(individual_km)