2015-06-04 62 views
5

在R的igraph软件包中,我努力绘制使用纬度/经度坐标作为图形布局的社交网络。使用地理坐标作为igraph r-package中的顶点坐标

想象一下这个简单的例子:与你认识的地理位置4个节点和连接的网络:

df<-data.frame("from" = c("Bob", "Klaus", "Edith", "Liu"), "to"= c("Edith", "Edith", "Bob", "Klaus")) 

这里有元数据的节点,让鲍勃住在纽约,克劳斯在柏林,伊迪丝在巴黎和刘在北京:

meta <- data.frame("name"=c("Bob", "Klaus", "Edith", "Liu"), "lon"=c(-74.00714, 13.37699, 2.34120, 116.40708), "lat"=c(40.71455, 52.51607, 48.85693, 39.90469)) 

我们做克的igraph对象...

g <- graph.data.frame(df, directed=T, vertices=meta) 

...我们定义我们的布局经度/纬度坐标

lo <- layout.norm(as.matrix(meta[,2:3])) 
plot.igraph(g, layout=lo) 

如果您用这些(真实)地理坐标这个例子中,你会发现它处于“相对”准确感觉到这些位置相对于彼此是正确的。然而,如果我绘制了很多像这样的坐标,世界笛卡尔地图看起来就是“伸出的”。

有没有一种方法可以真正在世界地图上绘制我的节点,以便坐标100%正确,并且我可以看到我的节点之间的连接?我真的想继续使用igraph软件包,因为它提供了许多我以后可能需要的功能,当我想分析节点之间的链接时。

+0

您是否考虑过从igraph节点制作数据框,然后使用ggplot子系统将它们绘制在地图上? – hrbrmstr

+0

对@ hrbrmstr的建议,这会创建世界地图,但是覆盖或整合边缘和igraph功能超出了我的想象。要求(地图) 国家< - 地图数据(“世界”) 国家< - 子集(国家,地区!=“南极洲”) ggplot(meta,aes(x = lon,y = lat))+ geom_point = 22,fill =“red”,size = 6)+ geom_polygon(data = countries,aes(x = long,y = lat,group = group),col =“grey30”,fill =“transparent”,lwd = 0) – lawyeR

+2

你需要在这里用'rescale = FALSE'参数调用'igraph :: plot()',否则它将沿两个维度的坐标重新调整为'[-1; 1]'间隔。 – deeenes

回答

6

正如我在评论中所建议的,解决方案的一个要素无疑是rescale = FALSE参数igraph::plot()。 OP问为什么ey会得到一个空的阴谋?这是因为绘图区域仍沿x和y轴限制在[-1; 1]区间内。这是默认的igraph::plot()。所以我们需要给xlim = c(-180, 180)ylim = c(-90, 90)参数。这已经给出了正确的定位。但是,如果我们的目标是要用世界地图生成一个图形,那么最好将igraph图形写入cairo SVG设备。然后,我们可以将地图放置在任何SVG编辑器的图形后面(例如Inkscape是一个很好的解决方案),我们仍然可以自由缩放和编辑图形和标签。为了做到这一点,需要设置一些其他参数igraph.plotting,但这已经与比例和美观有关。下面是我用来产生SVG输出的代码:

#!/usr/bin/Rscript 

require(igraph) 
require(Cairo) 

df <- data.frame("from" = c("Bob", "Klaus", "Edith", "Liu"), 
    "to" = c("Edith", "Edith", "Bob", "Klaus")) 

meta <- data.frame("name" = c("Bob", "Klaus", "Edith", "Liu"), 
    "lon" = c(-74.00714, 13.37699, 2.34120, 116.40708), 
    "lat" = c(40.71455, 52.51607, 48.85693, 39.90469)) 

g <- graph.data.frame(df, directed = TRUE, vertices = meta) 

lo <- layout.norm(as.matrix(meta[,2:3])) 

dpi = 1.0 
Cairo(file = 'map-graph.svg', type = "svg", 
    units = "in", 
    width = 4/dpi, 
    height = 2/dpi, 
    dpi = dpi) 

plot.igraph(g, 
    layout = lo, 
    xlim = c(-180, 180), 
    ylim = c(-90, 90), 
    rescale = FALSE, 
    edge.curved = TRUE, 
    edge.arrow.size = 10/dpi, 
    edge.arrow.width = 0.5/dpi, 
    vertex.label.dist = 50/dpi, 
    vertex.label.degree = 90/dpi, 
    vertex.size = 200/dpi, 
    vertex.label.cex = 21/dpi, 
    vertex.frame.color = NA, 
    vertex.label.color = '#FFFF00', 
    edge.color = '#FFFFFF', 
    vertex.label.family = 'sans-serif', 
    edge.width = 16/dpi) 

dev.off() 

当IGRAPH产生的SVG看起来不错,我们可以在Inkscape中打开它。然后导入(Ctrl+i)地图,如果它是像素图;或者如果它是矢量图形(例如PDF,SVG)则打开。手动缩放和放置地图以设置与SVG中图形相同的比例(即直到点到达正确位置) - 对于比例缩放,请在Inkscape中保存Ctrl。下面是这个方法的结果:

enter image description here

(地图图像,并可用于通过维基共享资源,非商业的公共使用)。

我认为igraph能够产生这样的数字,但这不是这个软件的主要目的,所以它有其局限性。在某些情况下,您可能会考虑使用一些专门设计用于执行此类操作的地理信息系统(GIS)软件。我没有这些经验,但qgis可能值得去看看。

+0

这是完美的。好的解决方案大圈子的建议也非常有用(http://flowingdata.com/2011/05/11/how-to-map-connections-with-great-circles/)以视觉上做我所需要的。 – willemr