Javascript 移除/禁用';t在D3力布局/力模拟中显示空节点

Javascript 移除/禁用';t在D3力布局/力模拟中显示空节点,javascript,d3.js,nodes,force-layout,Javascript,D3.js,Nodes,Force Layout,我有一个与此类似的问题:但那里的解决方案对我没有帮助 我的csv数据集有一些空的源和目标 我的csv看起来是这样的:(很抱歉,这不是真实的数据,因为它要大得多,但我希望这样可以做到) 所以我得到的是John、Alex和Charlie通过一个“空”节点连接。我想要的是它们不与任何其他节点连接。只有一个节点。 以下是我的代码片段: var simulation = d3.forceSimulation() .force("link", d3.forceLink())

我有一个与此类似的问题:但那里的解决方案对我没有帮助

我的csv数据集有一些空的源和目标 我的csv看起来是这样的:(很抱歉,这不是真实的数据,因为它要大得多,但我希望这样可以做到)

所以我得到的是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力布局和d3.v4力模拟进行了尝试,结果相同)


感谢您的帮助(对于任何错误,我深表歉意-英语不是我的第一语言,这是我在这里的第一个问题)

此问题可以通过以下方式解决:

  • 仅当值不是空字符串时,才基于源值和目标值存储节点
  • 仅当源和目标都不为空时才存储链接
与从解析的CSV数据集中删除记录不同,可以基于源和目标的存在填充一个新的
链接
数组

下面代码段中的功能演示

let csv='source,target\nJohn\n,Alex\nAlice,Bob\nEve,Carol\nDave,Bob\nCharlie,'
,输入=d3.csvParse(csv)
,nodesByName={}
,links=[]
input.forEach(函数(链接){
if(link.source)
//源不为空,记录节点
nodesByName[link.source]={name:link.source}
if(link.target)
//目标不为空,记录节点
nodesByName[link.target]={name:link.target}
if(link.source和link.target)
//源和目标都不是空的,记录链接
links.push({
来源:nodesByName[link.source]
,target:nodesByName[link.target]
})
})
console.log('--------------'))
console.log('节点')
console.log(nodesByName)
console.log('--------------'))
console.log('links'))
console.log(链接)

链接问题的解决方案应该可以解决您的问题。你尝试过什么吗?没有,正如我问题的第一行所述,我已经尝试过建议的解决方案。你能尝试过滤掉你不喜欢的数据吗?您能否说明为什么其他问题不能解决您的问题,或者您如何更改代码以采用建议的解决方案?就像@Mehdi的建议,我很确定这是一个副本。顺便说一句,欢迎来到stackOverflow。我们的期望是,你展示你已经尝试过的东西,我们从这里开始。应该遵守。
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; });
            }