Do utworzenia dokładnie zagnieżdżonego obiektu, którego chcesz, użyjemy kombinacji czystego JavaScript i metody D3 o nazwie d3.stratify
. Należy jednak pamiętać, że 7 milionów wierszy (patrz poniżej post scriptum ) to dużo do obliczenia.
Bardzo ważne jest, aby wspomnieć, że w tym proponowanym rozwiązaniu będziesz musiał rozdzielić Królestwa na różne tablice danych (na przykład przy użyciu Array.prototype.filter
). To ograniczenie występuje, ponieważ potrzebujemy węzła głównego, a w taksonomii linnańskiej nie ma związku między Królestwami (chyba że stworzysz „domenę” jako najwyższą rangę, która będzie pierwiastkiem dla wszystkich eukariontów, ale wtedy będziesz mieć to samo problem dla Archaea i Bakterii).
Załóżmy, że masz ten plik CSV (dodałem kilka wierszy) tylko z jednym Królestwem:
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
Na podstawie tego pliku CSV utworzymy tutaj tablicę o nazwie, tableOfRelationships
która, jak sama nazwa wskazuje, ma relacje między szeregami:
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
})
})
});
Dla powyższych danych jest to 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" |
+---------+----------------------+---------------+
Spójrz na null
rodzica Animalia
: dlatego powiedziałem ci, że musisz oddzielić zestaw danych od Kingdoms, null
w całej tabeli może być tylko jedna wartość.
Wreszcie, na podstawie tej tabeli, tworzymy hierarchię przy użyciu d3.stratify()
:
const stratify = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; });
const hierarchicalData = stratify(tableOfRelationships);
A oto wersja demo. Otwórz konsolę przeglądarki (fragment kodu nie jest zbyt dobry do tego zadania) i sprawdź kilka poziomów ( children
) obiektu:
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 : Nie wiem, jaki rodzaj danych stworzysz, ale naprawdę powinieneś unikać rang taksonomicznych. Cała taksonomia linnańska jest przestarzała, nie używamy już szeregów: ponieważ systematyka filogenetyczna została opracowana w połowie lat 60-tych, używamy tylko taksonów, bez żadnej rangi taksonomicznej (tutaj nauczyciel biologii ewolucyjnej). Jestem też bardzo ciekawy tych 7 milionów wierszy, ponieważ opisaliśmy nieco ponad 1 milion gatunków!
nan
dla Phylum zawierającego Magnoliopsida. Co tonan
jest Phylum to Anthophyta lub alternatywnie Magnolia (to stara Phylum Angiospermae).