Для создания нужного вложенного объекта мы будем использовать смесь чистого JavaScript и метода D3 с именем d3.stratify
. Тем не менее, имейте в виду, что 7 миллионов строк (см. Постскриптум ниже) - это много для вычисления.
Очень важно отметить, что для этого предлагаемого решения вам придется разделить Королевства в разных массивах данных (например, используя Array.prototype.filter
). Это ограничение возникает из-за того, что нам нужен корневой узел, и в таксономии Линнея нет никакой связи между королевствами (если вы не создадите «Домен» в качестве высшего ранга, который будет корнем для всех эукариот, но тогда у вас будет то же самое проблема для архей и бактерий).
Итак, предположим, у вас есть этот 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
На основе этого CSV мы создадим массив с именем, tableOfRelationships
который, как следует из названия, имеет отношения между рангами:
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
})
})
});
Для приведенных выше данных это 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" |
+---------+----------------------+---------------+
Взгляните null
как на родителя Animalia
: именно поэтому я сказал вам, что вам нужно разделить ваш набор данных по Kingdoms, null
во всей таблице может быть только одно значение.
Наконец, на основе этой таблицы мы создаем иерархию, используя d3.stratify()
:
const stratify = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; });
const hierarchicalData = stratify(tableOfRelationships);
И вот демо. Откройте консоль браузера (фрагмент кода не подходит для этой задачи) и проверьте несколько уровней ( children
) объекта:
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 : я не знаю, какой тип данных вы создадите, но вам действительно следует избегать таксономических рангов. Вся таксономия Линнея устарела, мы больше не используем ранги: поскольку филогенетическая систематика была разработана в середине 60-х годов, мы используем только таксоны без какого-либо таксономического ранга (здесь учитель эволюционной биологии). Кроме того, мне довольно любопытно эти 7 миллионов строк, так как мы описали чуть более 1 миллиона видов!
nan
для Типа, содержащего Магнолиопсиду. Что этоnan
? Типом является Антофита, или, в качестве альтернативы, Магнолия (это старый Phylum Angiospermae).