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

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

问题描述

在 R 的 igraph 包中,我正在努力使用纬度/经度坐标作为图形的布局来绘制社交网络.

想象一下这个简单的例子:一个有 4 个节点的网络,您知道其中的地理位置和连接:

df<-data.frame("from" = c("Bob", "Klaus", "Edith", "Liu"), "to"= c("Edith", "Edith",鲍勃",克劳斯"))

这里有节点的元数据,因此 Bob 住在纽约,Klaus 在柏林,Edith 在巴黎,Liu 在北京:

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

我们将 g 设为 igraph 对象...

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

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

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

如果您使用这些(真实的)地理坐标运行此示例,您会发现它是相对"准确的,因为这些位置相对于彼此是正确的.但是,如果我像这样绘制很多坐标,则世界笛卡尔地图看起来被拉长了".

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

解决方案

解决方案的一个要素无疑是 rescale = FALSE 参数到 igraph::plot() 正如我在评论中建议的那样.OP问为什么他们会得到一个空的情节?这是因为绘图区域仍然限于 [-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天全站免登陆