从打印输出(熊猫)获取表格

时间:2019-11-05 09:04:25

标签: python pandas ete3

我运行了一个名为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

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

您有一个如何处理打印输出的想法吗?

感谢您的帮助。

3 个答案:

答案 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)

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