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:
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 latrans
3,Animalia,Chordata,Mammalia,Cetacea,Delphinidae,Tursiops,Tursiops truncatus
1,Animalia,Chordata,Mammalia,Primates,Hominidae,Pan,Pan paniscus
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:
const data = d3.csvParse(csv);
const taxonomicRanks = data.columns.filter(d => d !== "RecordID");
const tableOfRelationships = [];
data.forEach(row => {
taxonomicRanks.forEach((d, i) => {
if (!tableOfRelationships.find(e => e.name === row[d])) tableOfRelationships.push({
name: row[d],
parent: row[taxonomicRanks[i - 1]] || null
})
})
});
Pour les données ci-dessus, voici tableOfRelationships
:
+---------+----------------------+---------------+
| (Index) | name | parent |
+---------+----------------------+---------------+
| 0 | "Animalia" | null |
| 1 | "Chordata" | "Animalia" |
| 2 | "Mammalia" | "Chordata" |
| 3 | "Primates" | "Mammalia" |
| 4 | "Hominidae" | "Primates" |
| 5 | "Homo" | "Hominidae" |
| 6 | "Homo sapiens" | "Homo" |
| 7 | "Carnivora" | "Mammalia" |
| 8 | "Canidae" | "Carnivora" |
| 9 | "Canis" | "Canidae" |
| 10 | "Canis latrans" | "Canis" |
| 11 | "Cetacea" | "Mammalia" |
| 12 | "Delphinidae" | "Cetacea" |
| 13 | "Tursiops" | "Delphinidae" |
| 14 | "Tursiops truncatus" | "Tursiops" |
| 15 | "Pan" | "Hominidae" |
| 16 | "Pan paniscus" | "Pan" |
+---------+----------------------+---------------+
Jetez un œil en null
tant que parent de Animalia
: 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()
:
const stratify = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; });
const hierarchicalData = stratify(tableOfRelationships);
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:
const csv = `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 latrans
3,Animalia,Chordata,Mammalia,Cetacea,Delphinidae,Tursiops,Tursiops truncatus
1,Animalia,Chordata,Mammalia,Primates,Hominidae,Pan,Pan paniscus`;
const data = d3.csvParse(csv);
const taxonomicRanks = data.columns.filter(d => d !== "RecordID");
const tableOfRelationships = [];
data.forEach(row => {
taxonomicRanks.forEach((d, i) => {
if (!tableOfRelationships.find(e => e.name === row[d])) tableOfRelationships.push({
name: row[d],
parent: row[taxonomicRanks[i - 1]] || null
})
})
});
const stratify = d3.stratify()
.id(function(d) {
return d.name;
})
.parentId(function(d) {
return d.parent;
});
const hierarchicalData = stratify(tableOfRelationships);
console.log(hierarchicalData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
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!
nan
pour le phylum contenant Magnoliopsida. C'est quoi çanan
? Le Phylum est Anthophyta, ou alternativement Magnolia (c'est l'ancien Phylum Angiospermae).