J'ai un csv de 7 millions d'enregistrements de biodiversité où les niveaux de taxonomie sont en colonnes. Par exemple:
RecordID,kingdom,phylum,class,order,family,genus,species
1,Animalia,Chordata,Mammalia,Primates,Hominidae,Homo,Homo sapiens
2,Animalia,Chordata,Mammalia,Carnivora,Canidae,Canis,Canis
3,Plantae,nan,Magnoliopsida,Brassicales,Brassicaceae,Arabidopsis,Arabidopsis thaliana
4,Plantae,nan,Magnoliopsida,Fabales,Fabaceae,Phaseoulus,Phaseolus vulgaris
Je veux créer une visualisation en D3, mais le format de données doit être un réseau, où chaque valeur différente de colonne est un enfant de la colonne précédente pour une certaine valeur. Je dois passer du csv à quelque chose comme ça:
{
name: 'Animalia',
children: [{
name: 'Chordata',
children: [{
name: 'Mammalia',
children: [{
name: 'Primates',
children: 'Hominidae'
}, {
name: 'Carnivora',
children: 'Canidae'
}]
}]
}]
}
Je ne suis pas venu avec une idée de comment faire cela sans utiliser un millier de boucles. Quelqu'un at-il une suggestion sur la façon de créer ce réseau sur python ou javascript?
javascript
python
d3.js
data-visualization
hierarchical-data
Andres Camilo Zuñiga Gonzalez
la source
la source
nan
pour le phylum contenant Magnoliopsida. C'est quoi çanan
? Le Phylum est Anthophyta, ou alternativement Magnolia (c'est l'ancien Phylum Angiospermae).Réponses:
Pour créer l'objet imbriqué exact que vous souhaitez, nous utiliserons un mélange de JavaScript pur et d'une méthode D3 nommée
d3.stratify
. Cependant, gardez à l'esprit que 7 millions de lignes (veuillez consulter le post scriptum ci-dessous) est beaucoup à calculer.Il est très important de mentionner que, pour cette solution proposée, vous devrez séparer les royaumes dans différents tableaux de données (par exemple, en utilisant
Array.prototype.filter
). Cette restriction se produit parce que nous avons besoin d'un nœud racine, et dans la taxonomie linnéenne, il n'y a pas de relation entre les royaumes (à moins que vous ne créiez "Domaine" comme premier rang, qui sera la racine de tous les eucaryotes, mais vous aurez alors la même problème pour les archées et les bactéries).Supposons donc que vous ayez ce CSV (j'ai ajouté quelques lignes supplémentaires) avec un seul royaume:
Sur la base de ce CSV, nous allons créer ici un tableau nommé
tableOfRelationships
qui, comme son nom l'indique, a les relations entre les rangs:Pour les données ci-dessus, voici
tableOfRelationships
:Jetez un œil en
null
tant que parent deAnimalia
: c'est pourquoi je vous ai dit que vous devez séparer votre ensemble de données par Kingdoms, il ne peut y en avoir qu'unnull
valeur dans l'ensemble du tableau.Enfin, sur la base de ce tableau, nous créons la hiérarchie en utilisant
d3.stratify()
:Et voici la démo. Ouvrez la console de votre navigateur (celle de l'extrait n'est pas très bonne pour cette tâche) et inspectez les différents niveaux (
children
) de l'objet:Afficher l'extrait de code
PS : Je ne sais pas quel type de dataviz vous allez créer, mais vous devriez vraiment éviter les rangs taxonomiques. Toute la taxonomie linnéenne est dépassée, nous n'utilisons plus de rangs: puisque la systématique phylogénétique a été développée au milieu des années 60, nous n'utilisons que des taxons, sans aucun rang taxonomique (professeur de biologie évolutive ici). De plus, je suis assez curieux de ces 7 millions de lignes, car nous avons décrit un peu plus d'un million d'espèces!
la source
Il est facile de faire exactement ce dont vous avez besoin en utilisant python et
python-benedict
bibliothèque (il est open source sur Github :Installation
pip install python-benedict
La première sortie d'impression sera:
La deuxième sortie imprimée sera:
la source
la source
Cela semble simple, alors je ne comprends peut-être pas votre problème.
La structure de données que vous souhaitez est un ensemble imbriqué de dictionnaires, de paires clé / valeur. Votre dictionnaire de royaume de niveau supérieur a une clé pour chacun de vos royaumes, dont les valeurs sont des dictionnaires de phylum. Un dictionnaire de phylum (pour un royaume) a une clé pour chaque nom de phylum et chaque clé a une valeur qui est un dictionnaire de classe, etc.
Pour simplifier le codage, vos dictionnaires de genre auront une clé pour chaque espèce, mais les valeurs pour les espèces seront des dictionnaires vides.
Cela devrait être ce que vous voulez; aucune bibliothèque étrange requise.
Pour le tester, j'ai utilisé vos données et
pprint
de la bibliothèque standard.avoir
En relisant votre question, vous voudrez peut-être un grand tableau de paires («lien d'un groupe plus général», «lien vers un groupe plus spécifique»). Autrement dit, «Animalia» renvoie à «Animalia: Chordata» et «Animalia: Chordata» à «Animalia: Chordata: Mammalia», etc. Malheureusement, le «nan» dans vos données signifie que vous avez besoin de noms complets à chaque lien. Si ( parents, enfants) sont ce que vous voulez, parcourez l’arbre de cette façon:
donnant:
la source
name
etchildren
comme demandé dans la question.En Python, une façon de coder un arbre est d'utiliser a
dict
, où les clés représentent les nœuds et la valeur associée est le parent du nœud:Un avantage de ceci est que vous vous assurez que les nœuds sont uniques, car
dicts
ils ne peuvent pas avoir de clés en double.Si vous voulez encoder un graphique dirigé plus général à la place (c'est-à-dire que les nœuds peuvent avoir plus d'un parent), vous pouvez utiliser des listes de valeurs et avoir les enfants représentés (ou les parents, je suppose):
Vous pouvez faire quelque chose de similaire avec les objets dans JS, en substituant les tableaux aux listes, si nécessaire.
Voici le code Python que j'ai utilisé pour créer le premier dict ci-dessus:
la source
La façon la plus simple de transformer vos données en hiérarchie est probablement d'utiliser l' opérateur d' imbrication intégré de D3
d3.nest()
:En enregistrant les fonctions clés via,
nest.key()
vous pouvez facilement spécifier la structure de votre hiérarchie. Tout comme Gerardo l'a expliqué dans sa réponse, vous pouvez utiliser la.columns
propriété exposée sur le tableau de données après avoir analysé votre CSV pour automatiser la génération de ces fonctions clés. Le code entier se résume aux lignes suivantes:Notez, cependant, que la hiérarchie résultante ne ressemble pas exactement à la structure demandée dans votre question car les objets sont
{ key, values }
au lieu de{ name, children }
; à propos, cela vaut également pour la réponse de Gerardo. Cela ne fait pas de mal pour les deux réponses, cependant, car les résultats peuvent être congestionnésd3.hierarchy()
en spécifiant une fonction d' accesseur pour les enfants :La démo suivante rassemble toutes les pièces:
Afficher l'extrait de code
Vous pouvez également consulter la conversion des valeurs et des clés d3.nest () en nom et enfants au cas où vous ressenteriez le besoin d'avoir exactement votre structure publiée.
la source
d3.nest
tant qu'il dure: il sera bientôt obsolète.Un défi amusant. Essayez ce code javascript. J'utilise l'ensemble de Lodash pour plus de simplicité.
Cela produit le résultat final (similaire) à ce que vous voulez.
la source
En fait, @Charles Merriam sa solution est très élégante.
Si vous souhaitez obtenir un résultat identique à la question, essayez comme suit.
la source