无法改变使用 networkD3 的 forceNetwork 创建的网络图中的 linkDistance
Unable to vary linkDistance in network graph created using forceNetwork of networkD3
我正在尝试使用 networkD3 包在 R 中创建力导向网络图。一切正常...
devtools::install_github('christophergandrud/networkD3')
library(networkD3)
links2 <- data.frame(
Source = c(0, 0, 0, 1, 2, 3),
Target = c(1, 4, 5, 3, 4, 5),
Value = c(1, 9.9, 10, 8.8, 6.6, 7.2))
nodes2 <- data.frame(ID = 0:5,
Group = c(1L, 1L, 1L, 2L, 1L, 2L))
# this works
forceNetwork(Links=links2, Nodes=nodes2,
Source="Source", Target="Target", Value="Value",
NodeID="ID", Group="Group")
... 直到我开始使用 linkDistance
参数。当我将其设置为我想要的 Value
的功能时,我得到一个网络图,其中包含设备左上角的单个节点。
# this doesn't work
forceNetwork(Links=links2, Nodes=nodes2,
Source="Source", Target="Target", Value="Value",
NodeID="ID", Group="Group",
linkDistance="function(d) { return d.value; }")
如有任何关于如何改变链接长度的建议,我将不胜感激。
我在 R Studio 版本 0.98.1103 中为 Windows 使用 R 版本 3.1.3,包 networkD3 版本 0.1.2.2。 (我最初使用来自 CRAN 的 networkD3 版本 0.1.2.1 遇到了这个问题。所以我从 GitHub 安装了最新版本并遇到了同样的问题。)
networkD3
包太棒了!!
经过详尽的调查,我找到了错误:networkD3
seems to depend on d3js
生成的 HTML/CSS/JavaScript 代码,它提供了生成的 d3.min.js
文件的核心网络代码。 linkDistance
特性是在 d3.min.js
中编码的,错误就是在那里发生的。
不幸的是,正如文件名所示,JavaScript 已缩小,但您可以从 d3js
站点访问未缩小的源代码,特别是 https://github.com/mbostock/d3/blob/master/d3.js。
如果您查看 d3.js
的第 6307 行(和周围的上下文),您会发现:
force.linkDistance = function(x) {
if (!arguments.length) return linkDistance;
linkDistance = typeof x === "function" ? x : +x;
return force;
};
此函数在初始化期间的某个时刻被调用,x
是您最初在对 forceNetwork()
的 R 调用中提供的 字符串 (顺便说一句,该字符串作为 JSON 数据以及所有其他输入数据嵌入到 index.html
文件中,该文件由 networkD3
生成。
重复一下,x
是一个 字符串 。这意味着 typeof(x)
将 return "string"
, 而不是 "function"
,因为第 6307 行正在检查。因此,将调用三元的第二个替代方案,+x
,这是 JavaScript 式强制转换为 number
,这将导致 NaN
。因此,NaN
通过所有 link 距离和坐标传播,一切都得到 f*!%ed。
这可以通过将其更改为来解决:
linkDistance = typeof x === "string" ? eval('('+x+')') : +x;
显然我将 "function"
更改为 "string"
,但我还必须添加一个 eval()
调用以实际将函数定义从字符串中拉出,以便所有未来的代码都能正常工作with linkDistance
会起作用,因为它都假定它是一个函数,而不是一个字符串。最后,我不得不用括号连接以确保函数定义被表达,否则,如果您使用 function
作为代码字符串的前导标记(您这样做了,他们在 networkD3
文档,这是最明智的做法),那么它将被视为函数语句,这意味着它不会被解析为实际的表达式语句,并且 eval()
调用将 return undefined
,当代码最终尝试在算术表达式中使用 undefined
值时,您最终会得到 NaN
,从而导致相同的错误。 (请参阅 What is the difference between a function expression vs declaration in JavaScript? and https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ 了解有关此区别的几个很好的来源,并且可能还有一百万个其他来源。)
我已经在我的机器上测试了上面的修复并且它有效。我想这应该作为一个错误报告给 d3js
人,但我觉得我已经在这里做了足够的工作并且不会被打扰。请随时向他们报告此事,使用我的 post 此处作为参考。
如果您希望对从 R 传递到 JavaScript 的值进行求值(即将字符串解析为函数),请将其包含在 htmlwidgets::JS 函数中。例如:
library(htmlwidgets)
forceNetwork(Links=links2, Nodes=nodes2,
Source="Source", Target="Target", Value="Value",
NodeID="ID", Group="Group",
linkDistance=JS('function(d) {', 'return d.value;', '}'))
我正在尝试使用 networkD3 包在 R 中创建力导向网络图。一切正常...
devtools::install_github('christophergandrud/networkD3')
library(networkD3)
links2 <- data.frame(
Source = c(0, 0, 0, 1, 2, 3),
Target = c(1, 4, 5, 3, 4, 5),
Value = c(1, 9.9, 10, 8.8, 6.6, 7.2))
nodes2 <- data.frame(ID = 0:5,
Group = c(1L, 1L, 1L, 2L, 1L, 2L))
# this works
forceNetwork(Links=links2, Nodes=nodes2,
Source="Source", Target="Target", Value="Value",
NodeID="ID", Group="Group")
... 直到我开始使用 linkDistance
参数。当我将其设置为我想要的 Value
的功能时,我得到一个网络图,其中包含设备左上角的单个节点。
# this doesn't work
forceNetwork(Links=links2, Nodes=nodes2,
Source="Source", Target="Target", Value="Value",
NodeID="ID", Group="Group",
linkDistance="function(d) { return d.value; }")
如有任何关于如何改变链接长度的建议,我将不胜感激。
我在 R Studio 版本 0.98.1103 中为 Windows 使用 R 版本 3.1.3,包 networkD3 版本 0.1.2.2。 (我最初使用来自 CRAN 的 networkD3 版本 0.1.2.1 遇到了这个问题。所以我从 GitHub 安装了最新版本并遇到了同样的问题。)
networkD3
包太棒了!!
经过详尽的调查,我找到了错误:networkD3
seems to depend on d3js
生成的 HTML/CSS/JavaScript 代码,它提供了生成的 d3.min.js
文件的核心网络代码。 linkDistance
特性是在 d3.min.js
中编码的,错误就是在那里发生的。
不幸的是,正如文件名所示,JavaScript 已缩小,但您可以从 d3js
站点访问未缩小的源代码,特别是 https://github.com/mbostock/d3/blob/master/d3.js。
如果您查看 d3.js
的第 6307 行(和周围的上下文),您会发现:
force.linkDistance = function(x) {
if (!arguments.length) return linkDistance;
linkDistance = typeof x === "function" ? x : +x;
return force;
};
此函数在初始化期间的某个时刻被调用,x
是您最初在对 forceNetwork()
的 R 调用中提供的 字符串 (顺便说一句,该字符串作为 JSON 数据以及所有其他输入数据嵌入到 index.html
文件中,该文件由 networkD3
生成。
重复一下,x
是一个 字符串 。这意味着 typeof(x)
将 return "string"
, 而不是 "function"
,因为第 6307 行正在检查。因此,将调用三元的第二个替代方案,+x
,这是 JavaScript 式强制转换为 number
,这将导致 NaN
。因此,NaN
通过所有 link 距离和坐标传播,一切都得到 f*!%ed。
这可以通过将其更改为来解决:
linkDistance = typeof x === "string" ? eval('('+x+')') : +x;
显然我将 "function"
更改为 "string"
,但我还必须添加一个 eval()
调用以实际将函数定义从字符串中拉出,以便所有未来的代码都能正常工作with linkDistance
会起作用,因为它都假定它是一个函数,而不是一个字符串。最后,我不得不用括号连接以确保函数定义被表达,否则,如果您使用 function
作为代码字符串的前导标记(您这样做了,他们在 networkD3
文档,这是最明智的做法),那么它将被视为函数语句,这意味着它不会被解析为实际的表达式语句,并且 eval()
调用将 return undefined
,当代码最终尝试在算术表达式中使用 undefined
值时,您最终会得到 NaN
,从而导致相同的错误。 (请参阅 What is the difference between a function expression vs declaration in JavaScript? and https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ 了解有关此区别的几个很好的来源,并且可能还有一百万个其他来源。)
我已经在我的机器上测试了上面的修复并且它有效。我想这应该作为一个错误报告给 d3js
人,但我觉得我已经在这里做了足够的工作并且不会被打扰。请随时向他们报告此事,使用我的 post 此处作为参考。
如果您希望对从 R 传递到 JavaScript 的值进行求值(即将字符串解析为函数),请将其包含在 htmlwidgets::JS 函数中。例如:
library(htmlwidgets)
forceNetwork(Links=links2, Nodes=nodes2,
Source="Source", Target="Target", Value="Value",
NodeID="ID", Group="Group",
linkDistance=JS('function(d) {', 'return d.value;', '}'))