javascript - 来自 CSV 的 D3 强制布局,每行有多个边
问题描述
我正在尝试从每行包含多个边的 CSV 创建 D3(v3) 强制布局:
"c.compound","mt.entry","mt.protein_names","tt.gene_name","tt.gene_product","omcl.omcl_clusterid"
"TCMDC-143527","A0A059UE90","Glycogen synthase kinase-3 beta splice variant X1","TcCLB.507993.80","glycogen synthase kinase 3, putative","OG5_126888"
"TCMDC-143376","A0A059UE90","Glycogen synthase kinase-3 beta splice variant X1","TcCLB.507993.80","glycogen synthase kinase 3, putative","OG5_126888"
"TCMDC-143527","A0A059UE90","Glycogen synthase kinase-3 beta splice variant X1","Tb427.10.13780","glycogen synthase kinase 3","OG5_126888"
"TCMDC-143376","A0A059UE90","Glycogen synthase kinase-3 beta splice variant X1","Tb427.10.13780","glycogen synthase kinase 3","OG5_126888"
...
我需要这种力布局来反映以下优势:
c.compound -> mt.accession
mt.entry -> omcl.omcl_clusterid
tt.gene_name -> omcl.omcl_clusterid
我是 D3 的新手,所以我从mbostock在 github 上提供的代码示例开始。此示例接收一个 CSV 文件,逐行解析它,并从 CSV 中提取 A 到 B 边(逐行),如下所示
source, target
"A", "B"
"B", "C"
...
我想我可以通过对每一行进行额外的迭代并将所有链接存储在一个数组中,然后正常进行,从而使示例中的代码适应我的需要,就像这样:
d3.csv("allomcl_putative_test.csv", function(error, links) {
if (error) throw error;
var nodesByName = {};
var rels = [];
// Create nodes for each unique source and target.
links.forEach(function(link) {
var compound = nodeByName(link["c.compound"]);
var mt = nodeByName(link["mt.entry"]);
var tt = nodeByName(link["tt.gene_name"]);
var omcl = nodeByName(link["omcl.omcl_clusterid"]);
rels.push({
"source": compound.name,
"target": mt.name
});
rels.push({
"source": mt.name,
"target": omcl.name
});
rels.push({
"source": tt.name,
"target": omcl.name
});
});
rels.forEach(function(d) {
link = {
"source": d.source,
"target": d.target
};
});
...
我已经登录到控制台,链接和节点都被正确收集,但我无法启动强制布局。Javascript 控制台会提示如下错误:
TypeError: r.source is undefined[Learn More]
d3.v3.min.js:4:22668
ao.layout.force/l.start
https://d3js.org/d3.v3.min.js:4:22668
<anonymous>
file:///root/to/my/file/test.js:74:7
Cn/u.send/<
https://d3js.org/d3.v3.min.js:1:11277
t
https://d3js.org/d3.v3.min.js:1:1563
i
https://d3js.org/d3.v3.min.js:1:10130
关于如何解决它的任何想法?
解决方案
发现了问题。边缘不能作为源或目标字符串(至少在 D3 v3 中),因此有必要添加创建链接传递索引而不是名称。为此,我首先调整了 nodeByName 函数:
function nodeByName(name) {
return nodesByName[name] || (nodesByName[name] = {
name: name,
index: nodeid++
});
}
... nodeid 是在 csv 解析之前创建的变量,并在每次创建节点时自动递增。
然后我更改了边缘创建代码块以使用这些索引:
rows.forEach(function(link) {
var compound = nodeByName(link["c.compound"]);
var mt = nodeByName(link["mt.entry"], link["mt.protein_names"]);
var tt = nodeByName(link["tt.gene_name"], link["tt.gene_product"]);
var omcl = nodeByName(link["omcl.omcl_clusterid"]);
rels.push({
"source": compound.index,
"target": mt.index
});
rels.push({
"source": mt.index,
"target": omcl.index
});
rels.push({
"source": tt.index,
"target": omcl.index
});
});
它现在按预期工作:
推荐阅读
- multidimensional-array - 如何通过对 3D 数组中的每个值求和来返回 2D 数组
- excel - 单独计算细胞变化
- vulkan - 是否应该尽量减少应用程序创建的命令池的数量?
- r - R-更改行顺序并保持列对一致
- python - 将 TFRecord 转换回 JPEG 图像
- ruby-on-rails - 如何通过整数值更改时区?
- android - 将 TabLayout 与折叠工具栏对齐
- java - WildFly - 创建具有长时间运行应用程序的应用程序
- java - 如何让 Gradle 将 Java 依赖项放在不同的目标目录中?
- node.js - 如何在 NodeJS Express 应用程序的多个文件中使用一个 Mysql 池连接