我运行了一个名为codeml的程序,该程序在python软件包ete3中实现。
这是codeml生成的模型的印刷品:
>>> print(model)
Evolutionary Model fb.cluster_03502:
log likelihood : -35570.938479
number of parameters : 23
sites inference : None
sites classes : None
branches :
mark: #0 , omega: None , node_ids: 8 , name: ROOT
mark: #1 , omega: 789.5325 , node_ids: 9 , name: EDGE
mark: #2 , omega: 0.005 , node_ids: 4 , name: Sp1
mark: #3 , omega: 0.0109 , node_ids: 6 , name: Seq1
mark: #4 , omega: 0.0064 , node_ids: 5 , name: Sp2
mark: #5 , omega: 865.5116 , node_ids: 10 , name: EDGE
mark: #6 , omega: 0.005 , node_ids: 7 , name: Seq2
mark: #7 , omega: 0.0038 , node_ids: 11 , name: EDGE
mark: #8 , omega: 0.067 , node_ids: 2 , name: Sp3
mark: #9 , omega: 999.0 , node_ids: 12 , name: EDGE
mark: #10 , omega: 0.1165 , node_ids: 3 , name: Sp4
mark: #11 , omega: 0.1178 , node_ids: 1 , name: Sp5
但是由于它只是印刷品,所以我需要将这些信息放入表中,例如:
Omega node_ids name
None 8 ROOT
789.5325 9 EDGE
0.005 4 Sp1
0.0109 6 Seq1
0.0064 5 Sp2
865.5116 10 EDGE
0.005 7 Sp3
0.0038 11 EDGE
0.067 2 Sp3
999.0 12 EDGE
0.1165 3 Sp4
0.1178 1 Sp5
因为我需要解析这些信息。
您有一个如何处理打印输出的想法吗?
感谢您的帮助。
答案 0 :(得分:2)
您的问题中有两个隐含假设的问题:
为什么首先打印模型?这不是以编程方式访问模型内部的好方法,因为它是供人类读取的,并且您无法确定在其__str__()
方法中是否省略了模型的某些信息,该方法用于印刷。我得说,您必须找出Evolutionary Model
的结构,将这种结构转换成字典,并使用pandas.DataFrame.from_dict从该字典创建数据框。
首先查看model.__dict__()
和model.__repr__()
。
如果您可以看一下定义Evolutionary Model
的代码,那么您当然可以直接查询Evolutionary Model
的结构并将其变成字典。
如果您只是想“解析”模型,那么,如果您只是想获得对其属性的编程访问权限,则将其放入数据框需要大量的工作。如果要获取模型的model.branches
属性的值,只需直接访问属性,例如branches
。
答案 1 :(得分:1)
我看了underlying code in model.py
似乎您可以使用s = model.__str__()
来获取此打印输出的字符串。从那里可以使用标准字符串操作解析字符串。我不知道您的字符串的确切形式,但是您的代码可能看起来像这样:
import pandas as pd
lines = s.split('\\n')
lst = []
first_idx = 6 # Skip the lines that are not of interest.
names = [field[:field.index(':')].strip() for field in lines[first_idx].split(',')]
for line in lines[first_idx:]:
if line:
row = [field[field.index(':')+1:].strip().strip("#") for field in line.split(',')]
lst.append(row)
df = pd.DataFrame(lst, columns=names)
可以使用更漂亮的方法来完成此任务,但可以完成工作。
答案 2 :(得分:1)
您可以使用StringIO
和applymap
from io import StringIO
import pandas as pd
df = pd.read_csv(StringIO(model.__repr__()), skiprows=6, names=['mark', 'omega', 'node_ids', 'name'])
df = df.applymap(lambda x: x.split(":")[1])
输出:
mark omega node_ids name
0 #0 None 8 ROOT
1 #1 789.5325 9 EDGE
2 #2 0.005 4 Sp1
3 #3 0.0109 6 Seq1
4 #4 0.0064 5 Sp2
5 #5 865.5116 10 EDGE
6 #6 0.005 7 Seq2
7 #7 0.0038 11 EDGE
8 #8 0.067 2 Sp3
9 #9 999.0 12 EDGE
10 #10 0.1165 3 Sp4
11 #11 0.1178 1 Sp5