【问题标题】:Build NumPy Array with for loop (list of lists?)使用 for 循环构建 NumPy 数组(列表列表?)
【发布时间】:2018-10-16 03:17:59
【问题描述】:

我正在尝试构建一个数组,其中每一行包含来自不同序列的 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: 列表赋值索引超出范围

有没有更好的方法来做到这一点?

【问题讨论】:

  • 请注意:范围默认从 0 开始,因此 reange(0, len(kmer))range(len(kamer)) 完全相同。
  • 不太清楚您要归档的内容。您在此处提供的代码不会重现该错误,因为可能您没有定义该类。看看minimal reproducible example。无论如何,如果您输入到 self.profile 的数组长度不同,numpy 就不是您想要的:[stackoverflow.com/questions/3386259/…
  • 如果我正确理解了您的代码,并且它按照您的想法运行,那么您只需将 self.profile[i] = self.kmers 替换为 self.profile.append(self.kmers) 就可以了。这样,self.profile 将包含长度为 k 和更短的序列列表,其中包含self.motifs 中指定的碱基,但不是self.motifs 中给出的顺序。如果这是您想要的,我会发布一个对您的代码稍作更正的答案。
  • @MarcosWappner 我想要 self.profile[i] = self.kmers 的原因是我想要一个来自 self.motif 中每个序列的 k-mers 列表。如果我使用 self.profile.append(self.kmers) 它将它们连接起来。
  • 您不会将它们连接起来,因为 self.kmer 是一个列表(您应该在某处初始化)。或者更确切地说,我认为这是一个来自你所做的事实的列表self.kmer.append(kmer[q])。列表可以包含任何类型的项目,并且可以根据需要混合和匹配。 self.kmers 将是一个(不断增长的)列表,而 self.profile 将包含该列表的所有阶段。

标签: python arrays python-3.x bioinformatics


【解决方案1】:

从 cmets 收集信息,我认为您想要的是以下内容:给定一个基序列表(在您的情况下,每个 50 个碱基长的核苷酸串),您想要长度为 k 的子序列(k-mers)出现在每一个中。编写代码的更 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] 等的列表(即 yor 主题中的 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 将有重复的序列。为避免这种情况,您可以编写额外的检查 (if km not in self.kmers),或者使用 sets,以避免重复。

如果您确实想要由图案分隔的 kmer 列表,您可以通过列表理解以更简单的方式完成:

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

【讨论】:

  • 我将如何编写它以便我可以完成整个过程,例如:在 self.motifs 的第一个核苷酸中,找到 k-mers,将 k-mers 存储在列表中,将该列表放入另一个list.... 然后对 self.motifs 中的下一个核苷酸字符串再次执行此过程 - 沿途附加每个列表?这样我的数据是对应的(即 self.motifs[0] 与 self.kmers[0] 与 self.profile[0] 一起使用)?
  • 如果我正确理解您的问题,请参阅编辑后的答案。但是,我不确定您希望 self.profile 包含什么。
  • 我确实得到了self.profile 的长度为 8 的列表。您是否确保使用空列表正确初始化?如果您使用的是 spyder 或类似的东西,请尝试重新启动内核。
  • 是的,我用一个空列表初始化。我正在使用 PyCharm 并确保我保存了我的更改。仍然得到不同的数字。我的 len(self.profile) 输出类似于 312。 编辑:我认为这可能是我的代码在其他地方的问题。感谢您的帮助。
  • 酷。我希望你不仅解决了你的问题,而且还学习了一些 python。
【解决方案2】:

Numpy 数组不能像 python 列表和字典那样动态增长。事实上,上次我读到,为了任意增长 Numpy 数组,需要创建一个新数组以达到所需的形状,然后从原始数组对象中复制一份,这并不是过于优化。

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

我的个人资料 = []

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

self.profile = np.array(my_profile)

【讨论】:

  • 在使用列表时将“self.profile[i] = self.kmers”更改为 self.profile.append(self.kmers)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 2016-07-31
  • 1970-01-01
相关资源
最近更新 更多