从打印输出中获取 table (pandas)

Get a table from a print output (pandas)

我 运行 在 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

但由于它只是印刷品,我需要将这些信息放入 table,例如:

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

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

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

感谢您的帮助。

你的问题中隐含的假设有两个问题:

为什么要打印?

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

先看看 model.__dict__()model.__repr__()

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

为什么是数据框?

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

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

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

您可以使用 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