I have a subclassOf hierarchy that can be represented as a dataframe. subjects are subclasses of objects. I would like to print it as an indented list, where indentation means that the term is a subclass of the term on the line above. I'm using a recursive function and feel like I'm pretty close: I can indent in, but I don't think I've found the right place to indent out (by decrementing prefix_level).
Apologies if this question isn't organized real well. I'm open to any solution. It doesn't have to build on what I've shown here.
import pandas as pd
current_direct_sco = pd.DataFrame(
{
"subject": {
986: "ENVO:01000025",
989: "ENVO:01000028",
990: "ENVO:01000029",
991: "ENVO:01000030",
1011: "ENVO:01000050",
1014: "ENVO:01000053",
1015: "ENVO:01000054",
1096: "ENVO:01000127",
1242: "ENVO:01000252",
1243: "ENVO:01000253",
},
"object": {
986: "ENVO:01000024",
989: "ENVO:01000024",
990: "ENVO:01000024",
991: "ENVO:01000024",
1011: "ENVO:01000029",
1014: "ENVO:01000030",
1015: "ENVO:01000030",
1096: "ENVO:01000024",
1242: "ENVO:00000873",
1243: "ENVO:00000873",
},
}
)
print(current_direct_sco)
| | subject | object |
|------|---------------|---------------|
| 986 | ENVO:01000025 | ENVO:01000024 |
| 989 | ENVO:01000028 | ENVO:01000024 |
| 990 | ENVO:01000029 | ENVO:01000024 |
| 991 | ENVO:01000030 | ENVO:01000024 |
| 1011 | ENVO:01000050 | ENVO:01000029 |
| 1014 | ENVO:01000053 | ENVO:01000030 |
| 1015 | ENVO:01000054 | ENVO:01000030 |
| 1096 | ENVO:01000127 | ENVO:01000024 |
| 1242 | ENVO:01000252 | ENVO:00000873 |
| 1243 | ENVO:01000253 | ENVO:00000873 |
import igraph as ig
g = ig.Graph.TupleList(
current_direct_sco.itertuples(index=False), directed=True, vertex_name_attr="label"
)
# requires pycairo
ig.plot(g)
roots = list(set(current_direct_sco["object"]) - set(current_direct_sco["subject"]))
print(roots)
['ENVO:00000873', 'ENVO:01000024']
def recurse_envo(starting_term):
global prefix_level
global prefix_chunk
global current_prefix
print(current_prefix + starting_term)
current_children = list(
current_direct_sco["subject"].loc[current_direct_sco["object"] == starting_term]
)
if len(current_children) > 0:
prefix_level = prefix_level + 1
current_prefix = prefix_chunk * prefix_level
for current_child in current_children:
recurse_envo(current_child)
for i in roots:
first_term = i
prefix_level = 0
prefix_chunk = " "
current_prefix = ""
recurse_envo(first_term)
This is the output.
ENVO:00000873
ENVO:01000252
ENVO:01000253
ENVO:01000024
ENVO:01000025
ENVO:01000028
ENVO:01000029
ENVO:01000050
ENVO:01000030
ENVO:01000053
ENVO:01000054
ENVO:01000127
But it should look like this (hand-drawn). For example, ENVO:01000127 is not a subclass of ENVO:01000030:
ENVO:00000873
ENVO:01000252
ENVO:01000253
ENVO:01000024
ENVO:01000025
ENVO:01000028
ENVO:01000029
ENVO:01000050
ENVO:01000030
ENVO:01000053
ENVO:01000054
ENVO:01000127
