<p>正如@gbofi的回答所示,将k-mer转换为<code>0</code>和{<cd2>}之间的整数非常简单。另一种方法是进行数学编码:</p>
<pre><code>def kmer_to_int(kmer):
return sum(4**i * "ATGC".index(x) for i, x in enumerate(kmer))
</code></pre>
<p>我没有测试过这是否比构建一个二进制字符串然后将其转换为int更快</p>
<p>此代码为输入中的第一个字符指定最低位位置,因此<code>"AT"</code>变成{<cd4>},或者{<cd5>}和{<cd6>}变成{<cd7>}或{<cd8>}。如果希望编码将第一个字母视为最重要的,请在生成器表达式中使用<code>enumerate(reversed(kmer))</code>而不是{<cd10>}。在</p>
<p>正如其他人评论的那样,这些整数只对给定长度<code>k</code>唯一。如果长度不同的字符串只在尾随的<code>A</code>个数上有所不同(例如<code>"ATG"</code>,<code>"ATGA"</code>,<code>"ATGAA"</code>,<code>"ATGAAA"</code>,等等,所有这些都编码为<code>36</code>)。在</p>
<p>至于你更广泛的目标是在一个更大的序列中计算特定k-mers的出现,我不确定你是否会看到用这种方式编码k-mers的优势。这些好处可能取决于数据集的详细信息。在</p>
<p>整数键的一个优点是它们允许您使用列表而不是字典来保存计数。您可以用<code>lst = [0] * 4**k</code>构建一个适当的列表,然后用<code>lst[kmer_to_int(kmer)] += 1</code>增加一个值。在词条数量相同的情况下,列表的开销确实比字典低,但我不确定差异是否会大到足以提供帮助。在</p>
<p>如果数据是稀疏分布的(也就是说,许多4**k个可能的k-mer序列从未出现在输入中),使用列表可能仍然会浪费大量内存,因为列表总是<code>4**k</code>个元素。更好的方法可能是使用其他一些方法来简化稀疏数据的<code>dict</code>代码。在</p>
<p>一种选择是对<code>dict</code>类的某些方法进行修改,以避免将结果集中的所有值初始化为<code>0</code>。如果您将增量代码改为执行<code>d[key] = d.get(key, 0) + 1</code>,那么无论{<cd25>}是否已经在字典中,它都可以工作。在</p>
<p>另一个选择是使用<code>collections.Counter</code>,而不是常规的<code>dict</code>。<code>Counter</code>类是专门为计算输入序列中的项的实例而设计的,这似乎正是您所做的。它认为它还没有看到的任何键的值是<code>0</code>。在</p>