Para criar o objeto aninhado exato desejado, usaremos uma mistura de JavaScript puro e um método D3 chamado d3.stratify
. No entanto, tenha em mente que 7 milhões de linhas (consulte o post scriptum abaixo) são muito para calcular.
É muito importante mencionar que, para esta solução proposta, você precisará separar os Reinos em diferentes matrizes de dados (por exemplo, usandoArray.prototype.filter
). Essa restrição ocorre porque precisamos de um nó raiz e, na taxonomia de Linna, não há relação entre reinos (a menos que você crie "Domínio" como uma classificação superior, que será a raiz de todos os eucariotos, mas você terá o mesmo problema para arquéias e bactérias).
Então, suponha que você tenha esse CSV (adicionei mais algumas linhas) com apenas um reino:
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
Com base nesse CSV, criaremos uma matriz aqui chamada tableOfRelationships
que, como o nome indica, possui os relacionamentos entre as fileiras:
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
})
})
});
Para os dados acima, este é o 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" |
+---------+----------------------+---------------+
Dê uma olhada em null
como pai Animalia
: foi por isso que eu lhe disse que você precisa separar seu conjunto de dados por reinos; só pode haver um null
valor em toda a tabela.
Por fim, com base nessa tabela, criamos a hierarquia usando d3.stratify()
:
const stratify = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; });
const hierarchicalData = stratify(tableOfRelationships);
E aqui está a demonstração. Abra o console do navegador (o do snippet não é muito bom para esta tarefa) e inspecione os vários níveis ( children
) do objeto:
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 : Não sei que tipo de dados você criará, mas deve evitar filas taxonômicas. Toda a taxonomia linnaeana está desatualizada, não usamos mais fileiras: como a sistemática filogenética foi desenvolvida em meados dos anos 60, usamos apenas táxons, sem nenhuma classificação taxonômica (professor de biologia evolutiva aqui). Além disso, estou bastante curioso sobre esses 7 milhões de linhas, pois descrevemos pouco mais de 1 milhão de espécies!
nan
para o Phylum contendo Magnoliopsida. O que é issonan
? O filo é Anthophyta, ou alternativamente Magnólia (é o antigo Phylum Angiospermae).