gpt4 book ai didi

javascript - 有没有办法将 CSV 列转换为层次关系?

转载 作者:行者123 更新时间:2023-12-02 23:10:01 25 4
gpt4 key购买 nike

我有一个包含 700 万条生物多样性记录的 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
3,Plantae,nan,Magnoliopsida,Brassicales,Brassicaceae,Arabidopsis,Arabidopsis thaliana
4,Plantae,nan,Magnoliopsida,Fabales,Fabaceae,Phaseoulus,Phaseolus vulgaris

我想在 D3 中创建可视化,但数据格式必须是网络,其中列的每个不同值都是特定值的前一列的子级。我需要从 csv 转到类似这样的内容:

{
name: 'Animalia',
children: [{
name: 'Chordata',
children: [{
name: 'Mammalia',
children: [{
name: 'Primates',
children: 'Hominidae'
}, {
name: 'Carnivora',
children: 'Canidae'
}]
}]
}]
}

我还没有想出如何在不使用一千个 for 循环的情况下做到这一点。有人对如何在 python 或 javascript 上创建这个网络有建议吗?

最佳答案

为了创建您想要的精确嵌套对象,我们将混合使用纯 JavaScript 和名为 d3.stratify 的 D3 方法。 。但是,请记住,700 万行(请参阅下面的post scriptum)的计算量很大。

值得一提的是,对于这个建议的解决方案,您必须在不同的数据数组中分离王国(例如,使用 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 :

<表类=“s-表”><标题>索引姓名父级 <正文>0“动物界”空1“脊索动物”“动物界”2“哺乳动物”“脊索动物”3“灵长类动物”“哺乳动物”4“人科”“灵长类动物”5“同性”“人科”6“智人”“同性”7“食肉目”“哺乳动物”8“犬科动物”“食肉目”9“犬”“犬科动物”10“犬”“犬”11“鲸类”“哺乳动物”12“海豚科”“鲸类”13“图西奥普”“海豚科”14“Tursiops truncatus”“图西奥普”15“平移”“人科”16“Pan paniscus”“平移”

看看null作为 Animalia 的父级:这就是为什么我告诉你,你需要将数据集按王国分开,只能有一个 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 年代中期发展起来的,我们只使用类群,没有任何分类等级(这里是进化生物学老师)。另外,我对这 700 万行很好奇,因为我们已经描述了超过 100 万个物种!

关于javascript - 有没有办法将 CSV 列转换为层次关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58827592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com