我正在尝试使用 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中使用R版本3.1.3 for Windows,包netD3版本0.1.2.2。 (我最初使用CRAN的networkD3版本0.1.2.1遇到了问题。所以我从GitHub安装了最新版本,并遇到了同样的问题。)
答案 0 :(得分:3)
networkD3
包非常棒!!
经过详尽的调查后,我追踪了错误:networkD3
生成的HTML / CSS / JavaScript代码似乎依赖d3js
,https://github.com/mbostock/d3/blob/master/d3.js提供{{1}文件是生成的Web代码的核心。 d3.min.js
内部d3.min.js
功能已在linkDistance
内编码,并且存在错误。
不幸的是,正如文件名所示,JavaScript已缩小,但您可以从d3js
网站访问非缩小来源,特别是在What is the difference between a function expression vs declaration in JavaScript?。
如果您查看d3.js
的第6307行(以及周围环境),您会发现:
force.linkDistance = function(x) {
if (!arguments.length) return linkDistance;
linkDistance = typeof x === "function" ? x : +x;
return force;
};
在初始化期间的某个时刻调用此函数,x
是您最初在forceNetwork()
的R调用中提供的字符串(顺便说一下,该字符串嵌入在index.html
生成的networkD3
文件作为JSON数据,以及所有其他输入数据。)
要重复,x
是字符串。这意味着,{630}正在检查,typeof(x)
将返回"string"
,不 "function"
。因此,将调用三元的第二个替代方法+x
,这是number
的JavaScript风格强制,这将导致NaN
。因此,NaN
通过所有链接距离和坐标传播,一切都得到f *!%ed。
可以通过将其更改为:
来解决此问题linkDistance = typeof x === "string" ? eval('('+x+')') : +x;
显然我已将"function"
更改为"string"
,但我还必须添加eval()
调用以实际从字符串中提取函数定义,以便将来使用的所有代码{ {1}}会起作用,因为它都假定它是一个函数,而不是一个字符串。最后,我不得不用括号连接以确保函数定义被表达化,否则,如果你使用linkDistance
作为代码字符串的前导标记(你做了,他们在function
中做了)文档,这是最明智的事情),然后它将被视为一个函数语句,这意味着它不会被解析为一个实际的表达式语句,networkD3
调用将返回{{ 1}},当代码最终尝试在算术表达式中使用eval()
值时,您最终得到undefined
,从而导致相同的错误。 (请参阅https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/和https://developer.apple.com/library/mac/documentation/AppKit/Reference/NSAccessibility_Protocol_Reference/index.html#//apple_ref/c/data/NSAccessibilityFocusedUIElementChangedNotification了解有关此区别的几个好消息来源,并且可能还有其他一百万个来源。)
我已经在我的机器上测试了上述修复程序,但它确实有效。我想这应该被报告为NaN
人的错误,但我觉得我在这里做了足够多的工作而且不会感到困扰。请使用我的帖子作为参考,随时向他们报告。
答案 1 :(得分:2)
如果您想要从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;', '}'))