1

我运行了一个在 python 包 ete3 中实现的名为 codeml 的程序。

这是由 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

因为我需要解析这些信息。

您知道如何处理打印输出吗?

谢谢你的帮助。

4

3 回答 3

2

您的问题中的隐含假设存在两个问题:

为什么要打印?

你为什么首先打印模型?这不是以编程方式访问模型内​​部的好方法,因为这是为人类阅读而制作的,您无法确定在__str__()用于打印的方法中是否省略了模型的某些信息。你必须找出它的Evolutionary Model结构,把这个结构变成一个字典,然后使用pandas.DataFrame.from_dict从这个字典创建一个数据框,我会说。

首先看一下model.__dict__()and model.__repr__()

如果你可以看一下定义的代码,Evolutionary Model当然可以直接查找 的结构Evolutionary Model并将其变成字典。

为什么是数据框?

如果您只想“解析”模型,那么如果您只是想以编程方式访问其属性,那么将其放入数据框中需要做很多额外的工作。只需直接访问属性,例如,model.branches如果您想获取branches模型属性的值。

于 2019-11-05T09:10:03.870 回答
1

我看了一下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)

有更漂亮的方法可以做到这一点,但它可以完成工作。

于 2019-11-05T09:14:02.540 回答
1

您可以使用StringIOapplymap

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
于 2019-11-05T09:22:14.660 回答