【ROSALIND】【练Python,学生信】65 从基因序列构建字符表

如果第一次阅读本系列文档请先移步阅读【ROSALIND】【练Python,学生信】00 写在前面 谢谢配合~

题目:
从基因序列构建字符表(Creating a Character Table from Genetic Strings)
Given: A collection of at most 100 characterizable DNA strings, each of length at most 300 bp.
所给:不超过100条可表征的DNA序列,每条序列不超过300bp。
Return: A character table for which each nontrivial character encodes the symbol choice at a single position of the strings. (Note: the choice of assigning '1' and '0' to the two states of each SNP in the strings is arbitrary.).
需得:一个字符表,其中每个字符在各条序列此位置的情况进行编码。(提醒:各位置赋值“1”或“0”是任意的。)
测试数据
ATGCTACC
CGTTTACC
ATTCGACC
AGTCTCCC
CGTCTATC
测试输出
10110
10100
生物学背景
在55 创建字符表中,我们从进化树推出了字符表。但在实际操作中情况是相反的,我们需要先生成字符表,再在这个基础上构建系统发育模型。现代遗传学中,我们常通过对SNP的分析实现这一过程,对于给定的一组序列,我们可以用某个核苷酸位点上的不同来将这组序列分成两组。
思路
对于我来说,这道题的题面非常晦涩难懂,我在看了所给示例和其他人的解答代码后才大概理解了要做什么,我们先来看一下测试数据,一共有5条序列:
ATGCTACC
CGTTTACC
ATTCGACC
AGTCTCCC
CGTCTATC
我们根据序列可以画出下面这幅图:

也就是说,所给的序列是“可表征的(characterizable)”,即在每一个位点(列)上,最多只存在两种可能,根据每个位点的情况都可以把这些序列分成两类。但一个类里只有超过一个元素才有意义,所以输出结果时把只有一个或没有不一样值的列给删掉了。在本例中,只有前两列有超过一个不一样值,因此结果为:
10110
10100
接下来就是如何用python实现,我再次抄了别人的解答代码(原地址:https://github.com/fedeoliv/Rosalind-Problems/blob/master/cstr.py)。可以看到,这个代码非常简洁紧凑,阅读难度也较大,我这里帮大家梳理一下过程。
首先,读入数据文件,将序列传入到get_character_table()函数中。
进入get_character_table()后,首先要把序列从横着的一行一行存储,变成竖着的一列一列存储。这里用的语句是''.join, zip(*dna_strings)。其中,zip(*)函数首先用星号(*)操作符解包,把之前完整的一个一个序列变成单个字符,然后zip再把每一条序列某一位上的元素挨个取出来,拼成一个新的字符串。
把新字符串拼好后,用map(s[0].__eq__, s)将每一个列所有字符都与第一个字符比较,如果一致会返回1,反之返回0,把这些结果拼起来。
最后,用sum(map(int, k))去判断每列有几个不一样的值,显然,如果整列都一样,sum的结果将会是0或len(k),如果只有一个不一样的值,结果会是1或len(k) - 1,排除掉这两个情况,剩下的就是最终要得到的结果了。
代码