网络图中的搜索框 [英] Search box in network Plot

查看:122
本文介绍了网络图中的搜索框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 networkD3 包的 forceNetwork()函数创建了一个蛋白质突变网络。它会在RStudio的查看器窗格中呈现。然后我可以将它保存为一个HTML文件,用于共享,保留动态性质(如点击节点,突出显示连接等)。



我的网络图的png版本如下所示:



这是我原始数据中前20%的表示,整个数据看起来更加庞大和复杂。

我需要能够将搜索添加到此ForceNetwork,以便特定的节点可以位于复杂的网络中。通过编辑packageD3包的副本并重新打包,可以轻松实现javascript或jquery的一部分。但我的主要挑战是添加包含搜索框的html代码。



我的主R代码如下所示:

  library(networkD3)
library(XLConnect)

wb < - loadWorkbook(input.xlsx)
nodes < ; readWorksheet(wb,sheet =Node,startRow = 1,startCol = 1,header = TRUE)
links < - readWorksheet(wb,sheet =Edges,startRow = 1,startCol = 1, header = TRUE)


fn < - forceNetwork(Links = links,Nodes = nodes,
Source =Source,Target =ID,Value =Combo ,
NodeID =Mutation,linkDistance = JS('function(d){return d.value * 50;}'),
Nodesize =IF,Group =Combo,radiusCalculation = JS(d.nodesize + 6),
zoom = T,有界= F,legend = T,
不透明度= 0.8,
fontSize = 16)

fn

我的灵感来自 jsfiddle
在这种情况下包含搜索的最佳方式是什么?我想到的选项是首先将呈现保存为html。然后阅读并编辑html并插入一段代码以进行搜索。
我尝试过使用Rhtml来做这件事,但这似乎并不重要。任何指针将不胜感激。

解决方案

尽管我对这种交互性并不满意,但我认为这将是展示如何使用 htmltools htmlwidgets 。后来,我将重新创建串扰,但现在,我将如何复制所提供的示例。



直接复制



  library(htmltools)
library(networkD3)

data(MisLinks)
data(MisNodes)

#如图所示做一个forceNetwork forceNetwork
fn < - forceNetwork(
Links = MisLinks,Nodes = MisNodes,Source =源,
Target =target,Value =value,NodeID =name,
Group =group,opacity = 0.4,zoom = TRUE


fn< - htmlwidgets :: onRender(
fn,
'
函数(el,x){
调试器;
var optArray = [ ];
for(var i = 0; i< x.nodes.name.length - 1; i ++){
optArray.push(x.nodes.name [i]);
}

optArray = optArray.sort();

$(function(){
$(#search)。autocomplete({
source:optArray
));
});

d3.select(。ui-widget button)。node()。onclick = sear chNode;

函数searchNode(){
debugger;
//找到节点

var selectedVal = document.getElementById(search)。value;
var svg = d3.select(el).select(svg);
var node = d3.select(el).selectAll(。node);

if(selectedVal ==none){
node.style(stroke,white)。style(stroke-width,1);
} else {
var selected = node.filter(function(d,i){
return d.name!= selectedVal;
});
selected.style(opacity,0);
var link = svg.selectAll(。link)
link.style(opacity,0);
d3.selectAll(。node,.link)。transition()
.duration(5000)
.style(opacity,1);






可浏览(
attachDependencies(
tagList(
标签$ head(
tags $ link(
href =http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css,
$ rel =stylesheet

),
HTML(
'
< div class =ui-widget>
<搜索< /按钮>
< / div>
'
),$ b $ (b
),
列表(
rmarkdown :: html_dependency_jquery(),
rmarkdown :: html_dependency_jqueryui()





串扰版



备注:串扰是实验性的,所以这可能会改变



我没有花时间去优化和完善,但是这里有一个版本,以示例为例,但使用串扰代替自定义代码和 jquery-ui 自动完成。
$ b

  library(htmltools) 
library(networkD3)


#演示实验性串音
#一旦我们开始转换
#htmlwidgets以使用本机串扰工作,

#devtoools :: install_github(rstudio / crosstalk)
库(串扰)

数据(错误链接)
数据(错误节点)

#如下所示制作forceNetwork?forceNetwork
fn < - forceNetwork(
Links = MisLinks,节点= MisNodes,Source =source,
Target =目标,Value =value,NodeID =name,
Group =group,opacity = 0.4,zoom = TRUE


sd < - SharedData $ new(MisNodes,key =〜name,group =grp1)

#没有自动完成,所以不是相同的
#但是会用这个而不是写新的东西
fs < - filter_select(
id =filter-node,
label =Search Nodes,
sharedData = sd,
group =〜name


fn< - htmlwidgets :: onRender(
fn,
'
function(el,x){
// get the串扰组
//我们在来自R
的SharedData中使用了grp1 var ct_grp = crosstalk.group(grp1);
调试器;
ct_grp
.var(filter)
.on(change,function(val){searchNode(val.value)});

函数searchNode(filter_nodes){
debugger;
//找到节点
var selectedVal = filter_nodes? filter_nodes:[];
var svg = d3.select(el).select(svg);
var node = d3.select(el).selectAll(。node);

if(selectedVal.length === 0){
node.style(opacity,1);
svg.selectAll(。link)。style(opacity,1);
} else {
var selected = node.filter(function(d,i){
return selectedVal.indexOf(d.name)> = 0;
});
node.style(opacity,0);
selected.style(opacity,1);
var link = svg.selectAll(。link)。style(opacity,0);
/ *
svg.selectAll(。node,.link)。transition()
.duration(5000)
.style(opacity,1);






可浏览(
tagList(






) b fs,
fn



I have created a Network of protein mutations using the forceNetwork() function of the networkD3 package. It get's rendered on the RStudio's "Viewer" pane.

I can then save this as an HTML file, for sharing, with the dynamic nature (like clicking nodes, highlighting connections etc) preserved.

A png version of my network plot looks like below:

This is a representation of a top 20% in my original data, and the complete data looks even more huge and complex.

I need to be able to add a search to this forceNetwork, so that then specific nodes can be located in a complex network. The javascript or jquery part of this can be easily achieved by editing the copy of package networkD3 and repackaging. But my main challenge is adding the html code for including a search box.

My main R code looks like this:

library(networkD3)
library(XLConnect)

wb <- loadWorkbook("input.xlsx")
nodes <- readWorksheet(wb, sheet="Node", startRow = 1, startCol = 1, header = TRUE)
links <- readWorksheet(wb, sheet="Edges", startRow = 1, startCol = 1, header = TRUE)


fn <- forceNetwork(Links = links, Nodes = nodes,
                   Source = "Source", Target = "ID", Value = "Combo",
                   NodeID = "Mutation", linkDistance = JS('function(d){return d.value * 50;}'), 
                   Nodesize = "IF", Group = "Combo", radiusCalculation = JS("d.nodesize+6"),
                   zoom = T, bounded = F, legend = T, 
                   opacity = 0.8,
                   fontSize = 16 )

fn

My inspiration has come from the jsfiddle by Simon Raper. What would be the best way to include a search in this situation? The option I have thought of is to first save the rendering as an html. Then read and edit the html and insert the piece of code for the search. I tried to use Rhtml for this, but it doesn't seem trivial. Any pointers would be greatly appreciated.

解决方案

Although I'm not crazy about this interactivity, I thought it would be a good opportunity for demonstrating how to use htmltools with htmlwidgets. Later, I will recreate with crosstalk, but for now, here is how I would replicate the example provided.

direct replication

library(htmltools)
library(networkD3)

data(MisLinks)
data(MisNodes)

# make a forceNetwork as shown in ?forceNetwork
fn <- forceNetwork(
  Links = MisLinks, Nodes = MisNodes, Source = "source",
  Target = "target", Value = "value", NodeID = "name",
  Group = "group", opacity = 0.4, zoom = TRUE
)

fn <- htmlwidgets::onRender(
  fn,
  '
function(el,x){
debugger;
  var optArray = [];
  for (var i = 0; i < x.nodes.name.length - 1; i++) {
    optArray.push(x.nodes.name[i]);
  }

  optArray = optArray.sort();

  $(function () {
    $("#search").autocomplete({
      source: optArray
    });
  });

  d3.select(".ui-widget button").node().onclick=searchNode;

  function searchNode() {
    debugger;
    //find the node

    var selectedVal = document.getElementById("search").value;
    var svg = d3.select(el).select("svg");
    var node = d3.select(el).selectAll(".node");

    if (selectedVal == "none") {
      node.style("stroke", "white").style("stroke-width", "1");
    } else {
      var selected = node.filter(function (d, i) {
        return d.name != selectedVal;
      });
      selected.style("opacity", "0");
      var link = svg.selectAll(".link")
      link.style("opacity", "0");
      d3.selectAll(".node, .link").transition()
        .duration(5000)
        .style("opacity", 1);
    }
  }
}  
  '
)

browsable(
  attachDependencies(
    tagList(
      tags$head(
        tags$link(
          href="http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css",
          rel="stylesheet"
        )
      ),
      HTML(
  '
  <div class="ui-widget">
      <input id="search">
      <button type="button">Search</button>
  </div>
  '     
      ),
      fn
    ),
    list(
      rmarkdown::html_dependency_jquery(),
      rmarkdown::html_dependency_jqueryui()
    )
  )
)

crosstalk version

note: crosstalk is experimental, so this might change

I did not spend time to optimize and perfect, but here is a version that sort-of does the same thing as the example but using crosstalk instead of custom code and a jquery-ui autocomplete.

library(htmltools)
library(networkD3)


# demonstrate with experimental crosstalk
#  this will get much easier once we start converting
#  htmlwidgets to work natively with crosstalk

#devtoools::install_github("rstudio/crosstalk")
library(crosstalk)

data(MisLinks)
data(MisNodes)

# make a forceNetwork as shown in ?forceNetwork
fn <- forceNetwork(
  Links = MisLinks, Nodes = MisNodes, Source = "source",
  Target = "target", Value = "value", NodeID = "name",
  Group = "group", opacity = 0.4, zoom = TRUE
)

sd <- SharedData$new(MisNodes, key=~name, group="grp1" )

# no autocomplete so not the same
#  but will use this instead of writing something new
fs <- filter_select(
  id = "filter-node",
  label = "Search Nodes",
  sharedData = sd,
  group = ~name
)

fn <- htmlwidgets::onRender(
  fn,
'
function(el,x){
  // get the crosstalk group
  //  we used grp1 in the SharedData from R
  var ct_grp = crosstalk.group("grp1");
debugger;
  ct_grp
    .var("filter")
    .on("change", function(val){searchNode(val.value)});

  function searchNode(filter_nodes) {
    debugger;
    //find the node
    var selectedVal = filter_nodes? filter_nodes : [];
    var svg = d3.select(el).select("svg");
    var node = d3.select(el).selectAll(".node");

    if (selectedVal.length===0) {
      node.style("opacity", "1");
      svg.selectAll(".link").style("opacity","1");
    } else {
      var selected = node.filter(function (d, i) {
        return selectedVal.indexOf(d.name) >= 0;
      });
      node.style("opacity","0");
      selected.style("opacity", "1");
      var link = svg.selectAll(".link").style("opacity", "0");
      /*
      svg.selectAll(".node, .link").transition()
        .duration(5000)
        .style("opacity", 1);
      */
    }
  }
}  
'
)

browsable(
  tagList(
    fs,
    fn
  )
)

这篇关于网络图中的搜索框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆