Je veux dessiner de belles données de structure arborescente avec Jupyter Notebook ou une application Web! Telle est ma motivation. J'utilise Python pour faciliter l'analyse des données d'origine et je voulais répéter l'analyse et la visualisation de manière interactive.
Python Il semble y avoir plusieurs façons de dessiner une arborescence en Python, et la première qui me vient à l'esprit est networkx et [graphviz]. J'utilise une bibliothèque de graphes telle que (https://graphviz.readthedocs.io/en/stable/), mais comme le but est d'analyser la structure du graphe en premier lieu, je pense que les expressions élaborées sont difficiles.
D'autre part, il existe ETE Toolkit en tant qu'outil d'analyse et de visualisation dédié aux structures arborescentes. Le modèle est représenté au format The Newick, qui semble être une représentation bien connue de la structure arborescente. Cela semble plutôt bon, mais compte tenu de la compatibilité sur le Web, je voulais utiliser quelque chose d'un peu plus polyvalent, comme JSON, pour décrire le modèle.
Javascript Un bon résumé du dessin des structures de graphe en Javascript peut être trouvé ici [https://qiita.com/d0nchaaan/items/c47dc74cfefd92516e28). Il y a plusieurs choses, mais en termes de polyvalence et de quantité d'informations, je pense que c'est D3.js. Il existe également une bibliothèque pour dessiner des arbres.
Donc, je vais essayer de dessiner une arborescence avec D3.js en utilisant Jupyter Notebook. Jupyter Notebook a une bonne affinité depuis le début car il peut exécuter du Javascript et dessiner du HTML tout en utilisant le noyau Python en utilisant la magie des cellules (%% javascript).
Comme méthode, vous pouvez utiliser la magie des cellules Javascript ou py_d3. Eh bien, le premier est difficile à comprendre intuitivement en utilisant RequireJS (voir ici). Ce dernier semble bien envelopper la magie cellulaire de Javascript. Ici, je vais expliquer le dessin en utilisant py_d3.
Quoi qu'il en soit, installez py_d3. Utilisez pip. pip install py_d3
Commencez par charger le module comme suit:
import py_d3
py_d3.load_ipython_extension(get_ipython())
Vous trouverez ci-dessous un exemple de devis de la page d'accueil. Le premier %% d3 5.12.0
spécifie la version de d3.js. Vous pouvez savoir quelle version est disponible en tapant «% d3 version».
%%d3 5.12.0
<g></g>
<style>
element {
height: 25px;
}
div.bar {
display: inline-block;
width: 20px;
height: 75px;
margin-right: 2px;
background-color: teal;
}
</style>
<script>
var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
d3.select("g").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", function(d) {
var barHeight = d * 5;
return barHeight + "px";
});
</script>
Vous pouvez vérifier la sortie du graphique comme indiqué ci-dessous.
En utilisant pleinement RequireJS, il est possible de saisir des objets et des variables calculés en Python dans la fonction Javascript définie. Cependant, ce n'est pas très différent de la sortie en JSON et de la lecture dans d3.js, donc si les données ne sont pas très volumineuses, il est facile de parcourir le fichier intermédiaire. Par exemple, préparez un fichier JSON à structure arborescente comme indiqué ci-dessous.
import json
data = {
"name": "A",
"children": [
{ "name": "B" },
{
"name": "C",
"children": [{ "name": "D" }, { "name": "E" }, { "name": "F" }]
},
{ "name": "G" },
{
"name": "H",
"children": [{ "name": "I" }, { "name": "J" }]
},
{ "name": "K" }
]
};
json_file = open('test.json', 'w')
json.dump(data, json_file)
Utilisez l'arborescence de d3 hierarchy pour dessiner l'arborescence. Après avoir chargé la structure de données JSON et créé une arborescence basée sur ces données, tout ce que vous avez à faire est d'ajuster le dessin SVG. Veuillez vous référer aux documents d3.js et SVG pour un réglage fin du dessin.
%%d3 5.12.0
<style>
.link {
fill: none;
stroke: #555;
stroke-opacity: 0.4;
stroke-width: 1.5px;
}
</style>
<svg width="800" height="600"></svg>
<script>
var width = 800;
var height = 600;
var g = d3.select("svg").append("g")
.attr("transform", "translate(80,0)");
console.log("data");
d3.json("test.json")
.then((data) => {
console.log(data);
var root = d3.hierarchy(data);
var tree = d3.tree(root).size([height, width - 160]);
tree(root);
var link = g.selectAll(".link")
.data(root.descendants().slice(1))
.enter()
.append("path")
.attr("class", "link")
.attr("d", (d) => {
return "M" + d.y + "," + d.x +
"C" + (d.parent.y + 100) + "," + d.x +
" " + (d.parent.y + 100) + "," + d.parent.x +
" " + d.parent.y + "," + d.parent.x;
});
var node = g.selectAll(".node")
.data(root.descendants())
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
node.append("circle")
.attr("r", 8)
.attr("fill", "#999");
node.append("text")
.attr("dy", 3)
.attr("x", function(d) { return d.children ? -12 : 12; })
.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
.attr("font-size", "200%")
.text(function(d) { return d.data.name; });
})
.catch((error)=>{
}
)
</script>
Recommended Posts