我希望沿着线的长度制作带有箭头(或类似的V形)的定向网络图...
该igraph
库似乎使用了polygon
接受的基本功能lty
指定行类型,但这些仅限于各种破折号.
有没有办法制作自定义符号(甚至使用三角形 pch
)在R中形成一条线?
制作图表的最小代码:
require(igraph) gr = graph_from_literal( A -+ B -+ C ) plot(gr,edge.curved=TRUE)
顺便说一句,如果支持这个,我可以使用另一个网络分析库.我问开发商,ggraph
他说不可能做到这一点.
Cytoscape
和RCy3
库用于创建网络图.
从这里安装cytoscape版本3及更高版本.然后启动cytoscape GUI(图形用户界面)会话.
这个答案中使用的版本是cytoscape: 3.4.0
和RCy3: 1.5.2
操作系统:Windows-7
# load libraries library('RCy3') # create cytoscape connection cy <- RCy3::CytoscapeConnection() RCy3::deleteAllWindows(cy) # delete all windows in cytoscape hideAllPanels(cy) # hide all panels # create node and edge data and create graphNEL object node.tbl <- data.frame(Node.Name = c('A', 'B', 'C')) edge.tbl <- data.frame(Gene.1 = c('A', 'B'), Gene.2 = c('B', 'C')) g <- cyPlot(node.tbl, edge.tbl) g # A graphNEL graph with directed edges # Number of Nodes = 3 # Number of Edges = 2 # create cytoscape window and display the graph window_title <- 'example' cw <- RCy3::CytoscapeWindow(window_title, graph=g, overwrite=FALSE) RCy3::displayGraph(cw) # set visual style and layout algorithm vis_style <- 'Curved' # getVisualStyleNames(cw)[7] RCy3::setVisualStyle(cw, vis_style) RCy3::layoutNetwork(obj = cw, layout.name = "circular") RCy3::layoutNetwork(obj = cw, layout.name = "kamada-kawai") # get all edges getAllEdges(cw) # [1] "A (unspecified) B" "B (unspecified) C" # get cytoscape supported line types supported_styles <- getLineStyles (cw) supported_styles # [1] "EQUAL_DASH" "PARALLEL_LINES" "MARQUEE_DASH" "MARQUEE_EQUAL" "SOLID" "FORWARD_SLASH" "DASH_DOT" "MARQUEE_DASH_DOT" # [9] "SEPARATE_ARROW" "VERTICAL_SLASH" "DOT" "BACKWARD_SLASH" "SINEWAVE" "ZIGZAG" "LONG_DASH" "CONTIGUOUS_ARROW" # set edge line type setEdgeLineStyleDirect(cw, "A (unspecified) B", supported_styles [16]) # "CONTIGUOUS_ARROW"
setEdgeLineStyleDirect(cw, "A (unspecified) B", supported_styles [9]) # "SEPARATE_ARROW"
# save network as image in the current working directory fitContent (cw) setZoom(cw, getZoom(cw) - 1) # adjust the value from 1 to a desired number to prevent cropping of network diagram saveImage(obj = cw, file.name = 'example', image.type = 'png', h = 700)
有关详细信息,请阅读?RCy3::setEdgeLineStyleDirect
.
另外,对于cytoscape边缘属性,请参见此处
安装RCy3:
# Install RCy3 - Interface between R and Cytoscape (through cyRest app) library('devtools') remove.packages("BiocInstaller") source("https://bioconductor.org/biocLite.R") biocLite("BiocGenerics") biocLite("bitops") install_github("tmuetze/Bioconductor_RCy3_the_new_RCytoscape")
为了做到这一点igraph
,我认为你需要深入研究plot.igraph
函数,找出它为顶点之间的曲线边生成贝塞尔曲线的位置,然后使用插值来获得沿这些边的点.使用该信息,您可以沿图形边缘绘制箭头段.
这是一种不同于您要求的方法,但我希望可以满足您的需求.而不是igraph
,我将ggplot2
与包中的ggnet2
功能一起使用GGally
.
基本方法是获取每个图形边缘的端点的坐标,然后沿着我们将绘制箭头段的每个边缘插入点.请注意,边缘是直线,因为ggnet2
不支持弯曲边缘.
library(ggplot2) library(GGally) # Create an adjacency matrix that we'll turn into a network graph m = matrix(c(0,1,0,0, 0,0,1,0, 1,0,0,1, 0,0,0,0), byrow=TRUE, nrow=4) # Plot adjacency matrix as a directed network graph set.seed(2) p = ggnet2(network(m, directed=TRUE), label=TRUE, arrow.gap=0.03)
这是图表的样子:
现在我们想要沿每条边添加箭头.为此,我们首先需要找出每条边的终点坐标.我们可以使用ggplot_build
以下方法从图形对象本身获取:
gg = ggplot_build(p)
图表数据存储在gg$data
:
gg$data
[[1]] x xend y yend PANEL group colour size linetype alpha 1 0.48473786 0.145219576 0.29929766 0.97320807 1 -1 grey50 0.25 solid 1 2 0.12773544 0.003986273 0.97026602 0.04720945 1 -1 grey50 0.25 solid 1 3 0.02670486 0.471530869 0.03114479 0.25883640 1 -1 grey50 0.25 solid 1 4 0.52459870 0.973637028 0.25818813 0.01431760 1 -1 grey50 0.25 solid 1 [[2]] alpha colour shape size x y PANEL group fill stroke 1 1 grey75 19 9 0.1317217 1.00000000 1 1 NA 0.5 2 1 grey75 19 9 0.0000000 0.01747546 1 1 NA 0.5 3 1 grey75 19 9 0.4982357 0.27250573 1 1 NA 0.5 4 1 grey75 19 9 1.0000000 0.00000000 1 1 NA 0.5 [[3]] x y PANEL group colour size angle hjust vjust alpha family fontface lineheight label 1 0.1317217 1.00000000 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 1 2 0.0000000 0.01747546 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 2 3 0.4982357 0.27250573 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 3 4 1.0000000 0.00000000 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 4
在上面的输出中,我们可以看到前四列gg$data[[1]]
包含每条边的端点坐标(并且它们的有向图的顺序正确).
现在我们有了每个边的终点,我们可以在两个端点之间插入点,在这两个端点处我们将在末尾用箭头绘制线段.以下功能可以解决这个问题.它为每个边缘采用一个端点数据帧,并返回一个调用列表geom_segment
(每个图形边缘一个)绘制n
箭头段.geom_segment
然后可以将该呼叫列表直接添加到我们的原始网络图中.
# Function that interpolates points between each edge in the graph, # puts those points in a data frame, # and uses that data frame to return a call to geom_segment to add the arrow heads add.arrows = function(data, n=10, arrow.length=0.1, col="grey50") { lapply(1:nrow(data), function(i) { # Get coordinates of edge end points x = as.numeric(data[i,1:4]) # Interpolate between the end points and put result in a data frame # n determines the number of interpolation points xp=seq(x[1],x[2],length.out=n) yp=approxfun(x[c(1,2)],x[c(3,4)])(seq(x[1],x[2],length.out=n)) df = data.frame(x=xp[-n], xend=xp[-1], y=yp[-n], yend=yp[-1]) # Create a ggplot2 geom_segment call with n arrow segments along a graph edge geom_segment(data=df, aes(x=x,xend=xend,y=y,yend=yend), colour=col, arrow=arrow(length=unit(arrow.length,"inches"), type="closed")) }) }
现在让我们运行该功能,将箭头添加到原始网络图中
p = p + add.arrows(gg$data[[1]], 15)
以下是图表的样子: