此问题遵循相关问题:How to read two lines from a file and create dynamics keys in a for-loop?
但是,问题的性质已经发展到我想要解决的某些复杂性。
以下是按空格分隔的数据结构。
chr pos M1 M2 Mk Mg1 F1_hybrid F1_PG F1_block S1 Sk1 S2 Sj
2 16229767 T/T T/T T/T G/T C|T 1|0 726 . T/C T/C T/C
2 16229783 C/C C/C C/C A/C G|C 0|1 726 G/C G/C G/C C|G
2 16229992 A/A A/A A/A G/A G|A 1|0 726 A/A A/A A/A A|G
2 16230007 T/T T/T T/T A/T A|T 1|0 726 A|T A|T A|T A|T
2 16230011 G/G G/G G/G G/G C|G 1|0 726 G/C C|G C|G G/C
2 16230049 A/A A/A A/A A/A T|A 1|0 726 A|T . A/T A/T
2 16230174 . . . C/C T|C 1|0 726 C|T T|C T|C C|T
2 16230190 A/A A/A A/A A/A T|A 1|0 726 T|G G|T T|G T|G
2 16230260 A/A A/A A/A A/A G|A 1|0 726 G/G G/G G/G G/G
说明:
上述文件中有两大类数据。来自Group M
的数据的样本名称以 M 开头,类似group S
的多个列名称以 S 开头。
还有一个混合列(由 F1_hybrid 表示)。
数据是位置线上的字符串。 F1_hybrid是用管(|)来分阶段区分这两个字母的。因此,来自F1的两个字符串值是C-G-G-A-C-T-T-T-G
,而另一个字符串值是T-C-A-T-G-A-C-A-A。其中一个字符串来自 M-group ,而另一个字符串来自 S-group 但我需要进行一些统计分析才能这样做。但是,我可以直观地看出,T-C-A-T-G-A-C-A-A字符串最有可能来自M组。
步骤:
我阅读第一行并使用列信息创建唯一键。
然后我读了第二行和第三行以及F1_hybrid中的值,即C | T和G | C。现在,我需要计算M组与S组之间存在多少GgC(解释为G给定C)与CgT(C给定T)。
然后在F1_hybrid中用第4(G | A)行读取第3个(G | C)。所以,州是GgG和AgC。同样,我现在认为M对S组中存在许多GcG与AgC。
因此,我正在尝试构建一个Markov-model
,它会计算来自F1的分阶段字符串的状态数,并将group M
与group S
中的观察点数计算在内。
我现在正在解释,如何基于F1_hyrbid计算任何XgY(X给定Y)的数量:
条件01:
M1
样本的第二行和第三行的状态为(T / T with C / C)。因为分隔符是斜杠(/)而不是管道(|),我们无法分辨M1样本所处的确切状态。但是,我们可以创建组合矩阵(用于现状的先前状态)
T T
C CgT CgT
C CgT CgT
现在,我们可以看出 4总CgT
如果这个条件满足,我们会继续做同样的矩阵。
条件02
对于来自M组的其他样品的情况也是如此,除了Mg1,其中G / T在A / C之前。所以,矩阵是:
G T
A AgG AgT
C CgG CgT
所以,在这里我们观察到1个CgT计数。
条件03:
但是,如果早期的状态 - 状态在两个状态(如A | T在位置16230007处,C | G在位置16230011处,对于样本Sk1)通过管道分阶段我们可以直接执行在该位置观察到的状态的相位状态计数,只有CgA和GgT,因此CgT的计数为0.
条件04: 如果其中一个状态具有管道(|)但其他状态具有斜杠(/),则该条件将与具有斜线的两个状态相同。
条件05: 如果previous_state或present_state中的任何一个是句点(。),则对于F1_hybrid所期望的状态,观察计数自动为零(0)。
所以,预期的输出应该是这样的:
pos M1 M2 Mk Mg1 H0 H1 S1 Sk1 S2 Sj
16..9783 4-CgT 4-CgT 4-CgT 1-CgT GgC CgT 0 1-CgT 1-CgT 1-CgT
16..9992 4-AgC 4-AgC 4-AgC 2-AgC GgG AgC 1-AgC 1-AgC 1-AgC 1-AgC,1-GgG
16..0007 4-TgA 4-TgA 4-TgA 1-AgG,1-TgA AgG TgA 2-TgA 2-TgA 2-TgA1 1-TgA
..................contd
或者,每列的字典格式值同样有效。对于位于16..9783位置的第一个M1而言,['4-CgT','4-CgT','4-CgT','4-CgT']
类似于.archive-container {
margin-top: 85px;
}
.archive-container h2 {
font-weight: normal;
margin-bottom: 30px;
}
.archive,
.year,
th {
font-family: 'Georgia', sans-serif;
font-weight: normal;
color: #a6a6a6;
font-size: 16px;
}
.archive:hover th,
.year:hover th {
color: #a6a6a6 !important;
opacity: 1 !important;
}
.archive a:link:hover {
color: #e69900 !important;
}
a:link {
font-weight: normal;
color: black;
/
}
table {
margin-right: 20px;
border-spacing: 25px 3px;
}
,而对于其他位置则相同。
答案 0 :(得分:3)
这个问题有点旧,但很有趣,因为你有一个非常清晰的规范,你需要帮助来编写代码。我将使用自上而下的方法公开解决方案,这是一种非常着名的方法,使用普通的旧python。它不应该适应大熊猫。
自上而下的方法对我意味着:如果你不知道如何写它,只需命名吧!
您有一个文件(或字符串)作为输入,并且您想要输出文件(或字符串)。看起来很简单,但是您希望合并行对以构建每个新行。这个想法是:
您现在还不知道如何编写行生成器。您不知道如何为每对构建新行。不要被困难所困扰,只需为解决方案命名即可。想象一下,你有一个函数get_rows
和一个函数build_new_row
。让我们写下这个:
def build_new_rows(f):
"""generate the new rows. Output may be redirected to a file"""
rows = get_rows(f) # get a generator on rows = dictionaries.
r1 = next(rows) # store the first row
for r2 in rows: # for every following row
yield build_new_row(r1, r2) # yield a new row built of the previous stored row and the current row.
r1 = r2 # store the current row, which becomes the previous row
现在,检查两个"缺失"功能:get_rows
和build_new_row
。
函数get_rows
很容易编写。这是主要部分:
header = process_line(next(f))
for line in f:
yield {k:v for k,v in zip(header, process_line(line))}
其中process_line
只是在空格上分割线条,例如使用re.split("\s+", line.strip())
。
第二部分是build_new_row
。仍然是自上而下的方法:您需要从预期的表中构建H0和H1,然后根据您暴露的条件为每个M和S构建H1的计数。假设您有一个计算H0和H1的pipe_compute
函数,以及一个为每个M和S构建H1计数的build_count
函数:
def build_new_row(r1, r2):
"""build a row"""
h0, h1 = pipe_compute(r1["F1_hybrid"], r2["F1_hybrid"])
# initialize the dict whith the pos, H0 and H1
new_row = {"pos":r2["pos"], "H0":h0, "H1":h1}
for key in r1.keys():
if key[0] in ("M", "S"):
new_row[key] = build_count(r1[key], r2[key], h1)
return new_row
你现在几乎拥有一切。看一下pipe_compute
:它正是你在条件03中所写的内容。
def pipe_compute(v1, v2):
"""build H0 H1 according to condition 03"""
xs = v1.split("|")
ys = v2.split("|")
return [ys[0]+"g"+xs[0], ys[1]+"g"+xs[1]]
对于buid_count
,坚持自上而下的方法:
def build_count(v1, v2, to_count):
"""nothing funny here: just follow the conditions"""
if is_slash_count(v1, v2): # are conditions 01, 02, 04 true ?
c = slash_count(v1, v2)[to_count] # count how many "to_count" we find in the 2 x 2 table of condtions 01 or 02.
elif "|" in v1 and "|" in v2: # condition 03
c = pipe_count(v1, v2)[to_count]
elif "." in v1 or "." in v2: # condition 05
return '0'
else:
raise Exception(v1, v2)
return "{}-{}".format(c, to_count) # n-XgY
我们还在下降。我们什么时候有is_slash_count
?两个斜线(条件01和02)或一个斜杠和一个管道(条件04):
def is_slash_count(v1, v2):
"""conditions 01, 02, 04"""
return "/" in v1 and "/" in v2 or "/" in v1 and "|" in v2 or "|" in v1 and "/" in v2
函数slash_count
只是条件01和02的2 x 2表:
def slash_count(v1, v2):
"""count according to conditions 01, 02, 04"""
cnt = collections.Counter()
for x in re.split("[|/]", v1): # cartesian product
for y in re.split("[|/]", v2): # cartesian product
cnt[y+"g"+x] += 1
return cnt # a dictionary XgY -> count(XgY)
函数pipe_count
更简单,因为您只需计算pipe_compute
的结果:
def pipe_count(v1, v2):
"""count according to condition 03"""
return collections.Counter(pipe_compute(v1, v2))
现在你已经完成了(并且已经完成)了。我得到的结果与你的期望略有不同,但你肯定已经看到了我的错误(s?):
pos M1 M2 Mk Mg1 H0 H1 S1 Sk1 S2 Sj
16229783 4-CgT 4-CgT 4-CgT 1-CgT GgC CgT 0 1-CgT 1-CgT 1-CgT
16229992 4-AgC 4-AgC 4-AgC 1-AgC GgG AgC 2-AgC 2-AgC 2-AgC 1-AgC
16230007 4-TgA 4-TgA 4-TgA 1-TgA AgG TgA 2-TgA 2-TgA 2-TgA 0-TgA
16230011 4-GgT 4-GgT 4-GgT 2-GgT CgA GgT 1-GgT 1-GgT 1-GgT 1-GgT
16230049 4-AgG 4-AgG 4-AgG 4-AgG TgC AgG 1-AgG 0 1-AgG 1-AgG
16230174 0 0 0 4-CgA TgT CgA 1-CgA 0 1-CgA 1-CgA
16230190 0 0 0 4-AgC TgT AgC 0-AgC 0-AgC 0-AgC 0-AgC
16230260 4-AgA 4-AgA 4-AgA 4-AgA GgT AgA 0-AgA 0-AgA 0-AgA 0-AgA
重要的是,除了这个特定问题的解决方案之外,我使用的方法和广泛用于软件开发的方法。代码可能会有很大改进。