Remove/Don在 D3 Force Layout/Force Simulation 中不显示空节点
Remove/Don't show empty node in D3 Force Layout / Force Simulation
我有一个类似的问题:但是那里的解决方案对我没有帮助。
我的 csv 数据集有一些空的源和目标
我的 csv 看起来像这样:(抱歉,这不是真实数据,因为它要大得多,但我希望这样做)
John,
,Alex
Alice,Bob
Eve,Carol
Dave,Bob
Charlie,
所以我得到的是通过 "empty" 节点连接的 John、Alex 和 Charlie。我想要的是它们与任何其他节点没有任何连接。只是一个节点。
这是我的代码片段:
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("x", d3.forceX(width / 2).strength(0.8))
.force("y", d3.forceY(height / 2).strength(0.8))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collide",d3.forceCollide().radius(d => d.r * 10))
.force("charge", d3.forceManyBody().strength(-100));
d3.csv("myData.csv", function(error, links) {
if (error) throw error;
var nodesByName = {}
links.forEach(function(link) {
link.source = nodesByName[link.source] || (nodesByName[link.source] = {name: link.source});
link.target = nodesByName[link.target] || (nodesByName[link.target] = {name: link.target});
});
var nodes = d3.values(nodesByName);
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 4.5)
.on("mouseover", tooltipOn)
.on("mouseout", tooltipOff)
simulation
.nodes(nodes)
.on("tick", tick)
.force("link").links(links);
function tick() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
(我用d3.v3 force layout和d3.v4 force simulation试过,结果一样)
感谢您的帮助(对于任何错误我深表歉意 - 英语不是我的母语,这是我的第一个问题)
这个问题可以通过以下方式解决:
- 根据源值和目标值存储节点,仅当值不是空字符串时
- 仅当源和目标都不为空时才存储链接。
不是从已解析的 CSV 数据集中删除记录,而是可以根据源和目标的存在填充新的 links
数组。
下面代码段中的功能演示
let csv = 'source,target\nJohn,\n,Alex\nAlice,Bob\nEve,Carol\nDave,Bob\nCharlie,'
, input = d3.csvParse(csv)
, nodesByName = {}
, links = []
input.forEach(function(link) {
if (link.source)
// source is not empty, record node
nodesByName[link.source] = {name: link.source}
if (link.target)
// target is not empty, record node
nodesByName[link.target] = {name: link.target}
if (link.source && link.target)
// both source and target are not empty, record link
links.push({
source: nodesByName[link.source]
, target: nodesByName[link.target]
})
})
console.log('-------------')
console.log('nodes')
console.log(nodesByName)
console.log('-------------')
console.log('links')
console.log(links)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-dsv/1.0.8/d3-dsv.min.js"></script>
我有一个类似的问题:
我的 csv 数据集有一些空的源和目标 我的 csv 看起来像这样:(抱歉,这不是真实数据,因为它要大得多,但我希望这样做)
John,
,Alex
Alice,Bob
Eve,Carol
Dave,Bob
Charlie,
所以我得到的是通过 "empty" 节点连接的 John、Alex 和 Charlie。我想要的是它们与任何其他节点没有任何连接。只是一个节点。 这是我的代码片段:
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("x", d3.forceX(width / 2).strength(0.8))
.force("y", d3.forceY(height / 2).strength(0.8))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collide",d3.forceCollide().radius(d => d.r * 10))
.force("charge", d3.forceManyBody().strength(-100));
d3.csv("myData.csv", function(error, links) {
if (error) throw error;
var nodesByName = {}
links.forEach(function(link) {
link.source = nodesByName[link.source] || (nodesByName[link.source] = {name: link.source});
link.target = nodesByName[link.target] || (nodesByName[link.target] = {name: link.target});
});
var nodes = d3.values(nodesByName);
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 4.5)
.on("mouseover", tooltipOn)
.on("mouseout", tooltipOff)
simulation
.nodes(nodes)
.on("tick", tick)
.force("link").links(links);
function tick() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
(我用d3.v3 force layout和d3.v4 force simulation试过,结果一样)
感谢您的帮助(对于任何错误我深表歉意 - 英语不是我的母语,这是我的第一个问题)
这个问题可以通过以下方式解决:
- 根据源值和目标值存储节点,仅当值不是空字符串时
- 仅当源和目标都不为空时才存储链接。
不是从已解析的 CSV 数据集中删除记录,而是可以根据源和目标的存在填充新的 links
数组。
下面代码段中的功能演示
let csv = 'source,target\nJohn,\n,Alex\nAlice,Bob\nEve,Carol\nDave,Bob\nCharlie,'
, input = d3.csvParse(csv)
, nodesByName = {}
, links = []
input.forEach(function(link) {
if (link.source)
// source is not empty, record node
nodesByName[link.source] = {name: link.source}
if (link.target)
// target is not empty, record node
nodesByName[link.target] = {name: link.target}
if (link.source && link.target)
// both source and target are not empty, record link
links.push({
source: nodesByName[link.source]
, target: nodesByName[link.target]
})
})
console.log('-------------')
console.log('nodes')
console.log(nodesByName)
console.log('-------------')
console.log('links')
console.log(links)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-dsv/1.0.8/d3-dsv.min.js"></script>