使用地理坐标作为igraph r-package中的顶点坐标 [英] Using geo-coordinates as vertex coordinates in the igraph r-package

查看:531
本文介绍了使用地理坐标作为igraph r-package中的顶点坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



想象一下这个简单的例子:在R的igraph软件包中,我正在努力绘制一个使用纬度/经度坐标作为图形布局的社交网络。一个包含4个节点的网络,其中您知道地理位置和连接:

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


$ b这里有节点的元数据,所以Bob住在纽约,柏林的Klaus,巴黎的Edith,北京:

  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图形对象...

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

。 ..并且我们将我们的布局定义为经度/纬度坐标


$ b $

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

如果你用这些(真实)地理坐标运行这个例子,从某种意义上说,它是相对准确的,因为这些位置相对于彼此是正确的。然而,如果我绘制了很多像这样的坐标,世界笛卡尔地图看起来就像是伸展出来的。

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

/ div>

这个解决方案的一个元素无疑是 rescale = FALSE 参数给 igraph :: plot() [ - 1; 1] 沿x轴和y轴的间隔。这是 igraph :: plot()的默认值。所以我们需要给 xlim = c(-180,180) ylim = c(-90,90)参数。这已经给出了正确的定位。但是,如果我们的目标是要用世界地图生成一个图形,也许最好将igraph图形写入cairo SVG设备。然后,我们可以将地图放在任何SVG编辑器的图表后面(例如,大概值得一看。


In the igraph package for R, I am struggling to plot a social network using latitude/longitude coordinates as the layout of the graph.

Imagine this simple example: a network with 4 nodes of which you know the geographical location and the connections:

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

Here you have the meta-data for the nodes, so that Bob lives in NY, Klaus in Berlin, Edith in Paris and Liu in Bejing:

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))

We make g the igraph object...

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

...and we define our layout as the longitude/latitude coordinates

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

If you run this example with these (real) geo-coordinates, you'll see that it is "relatively" accurate in the sense that the locations are right relative to each other. However, if I plot a lot of coordinates like this, the worlds cartesian map looks "stretched out".

Is there a way I can really plot my nodes on a world map so that the coordinates are 100% right and I get to see the connections between my nodes? I really want to keep using the igraph package as it offers a lot of functionalities I might need later on when I want to analyze the links between nodes.

解决方案

One element of the solution is no doubt the rescale = FALSE parameter to igraph::plot() as I suggested in comment. OP asked why ey gets an empty plot with this? It's because the plotting area is still limited to the [-1; 1] interval along both x and y axes. This is default of igraph::plot(). So we need to give xlim = c(-180, 180) and ylim = c(-90, 90) parameters. This already gives a correct positioning. However, if our aim is to produce a figure with the map of the world, maybe it is the best to write the igraph plot onto a cairo SVG device. Then we will be able to place the map behind the graph in any SVG editor (e.g. Inkscape is a great solution), and we are still free to scale and edit the graph and the labels. For doing this, some other igraph.plotting parameters necessary to be set, but this is already about proportions and aesthetics. Here is the code I used to produce the SVG output:

#!/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()

When the SVG produced by igraph looks fine, we can open it in Inkscape. Then import (Ctrl+i) the map in case it is pixmap; or open if it is vector graphics (e.g. PDF, SVG). Manually scale and position the map to set the same scale as the graph in the SVG (i.e. until the points get to their right place) – for proportional scaling, hold the Ctrl in Inkscape. Here is the result of this method:

(The map image is made available for non-commercial public use by Wikimedia Commons).

I think igraph is capable to produce figures like this, but this is not the primary aim of this software, so it has its limitations. At some point you might consider to use some Geographic Information System (GIS) software which is designed exactly to do things like this. I have no experience with those, but qgis probably worths to take a look at.

这篇关于使用地理坐标作为igraph r-package中的顶点坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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