Per creare esattamente l'oggetto nidificato desiderato, useremo un mix di JavaScript puro e un metodo D3 denominato d3.stratify
. Tuttavia, tieni presente che 7 milioni di righe (vedi il post scriptum seguito) sono molte da calcolare.
È molto importante ricordare che, per questa soluzione proposta, dovrai separare i Kingdoms in matrici di dati diverse (ad esempio, usando Array.prototype.filter
). Questa restrizione si verifica perché abbiamo bisogno di un nodo radice e nella tassonomia linnaea non esiste alcuna relazione tra Regni (a meno che tu non crei "Dominio" come primo rango, che sarà la radice di tutti gli eucarioti, ma avrai lo stesso problema per Archaea e batteri).
Quindi, supponiamo di avere questo CSV (ho aggiunto alcune altre righe) con un solo Regno:
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
Sulla base di quel CSV, creeremo qui un array chiamato tableOfRelationships
che, come suggerisce il nome, ha le relazioni tra i ranghi:
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
})
})
});
Per i dati sopra, questo è il 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" |
+---------+----------------------+---------------+
Dai un'occhiata a null
come genitore di Animalia
: ecco perché ti ho detto che devi separare il tuo set di dati per Kingdoms, può essercene solo unonull
valore nell'intera tabella.
Infine, basato su quella tabella, creiamo la gerarchia usando d3.stratify()
:
const stratify = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; });
const hierarchicalData = stratify(tableOfRelationships);
Ed ecco la demo. Apri la console del browser (quella dello snippet non è molto adatta per questa attività) e controlla i diversi livelli ( children
) dell'oggetto:
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 : Non so che tipo di dataviz creerai, ma dovresti davvero evitare i ranghi tassonomici. L'intera tassonomia linnaea è obsoleta, non usiamo più i ranghi: poiché la sistematica filogenetica è stata sviluppata a metà degli anni '60, usiamo solo i taxa, senza alcun grado tassonomico (insegnante di biologia evoluzionistica qui). Inoltre, sono abbastanza curioso di questi 7 milioni di file, poiché abbiamo descritto poco più di 1 milione di specie!
nan
per il Phylum contenente Magnoliopsida. Che cos'ènan
? Il Phylum è Anthophyta, o in alternativa Magnolia (è il vecchio Phylum Angiospermae).