2015-06-04 3 views
5

В пакете igraph для R я изо всех сил пытаюсь построить социальную сеть, используя координаты широты/долготы как макет графика.Использование геокоординированных координат в координатах вершин в igraph r-пакете

Представьте себе этот простой пример: сеть с 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 превосходят меня. требующие (карты) страны <- map_data ("world") страны <- подмножество (страны, регион! = "Антарктида") 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

Вы должны вызвать здесь 'igraph :: plot()' с параметром 'rescale = FALSE', в противном случае он пересказывает координаты вдоль обоих измерений в' [-1; 1] 'интервал. – deeenes

ответ

6

Одним из элементов решения, без сомнения, является параметр rescale = FALSE на igraph::plot(), как я предложил в комментарии. ОП спросил, почему у этого человека есть пустой сюжет? Это связано с тем, что область графика по-прежнему ограничена интервалом [-1; 1] вдоль осей x и y. По умолчанию используется значение igraph::plot(). Поэтому мы должны дать параметры xlim = c(-180, 180) и ylim = c(-90, 90). Это уже дает правильное позиционирование. Однако, если наша цель состоит в том, чтобы создать фигуру с картой мира, возможно, лучше написать графический график на устройстве SVG cairo. Затем мы сможем разместить карту за графиком в любом редакторе 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() 

Когда SVG производства igraph выглядит хорошо, мы можем открыть его в Inkscape. Затем импортируйте (Ctrl+i) карту в случае, если это pixmap; или открыть, если это векторная графика (например, PDF, SVG). Вручную масштабируйте и расположите карту, чтобы установить тот же масштаб, что и график в SVG (т. Е. До тех пор, пока точки не попадут в нужное место) - для пропорционального масштабирования удерживайте Ctrl в Inkscape. Вот результат этого метода:

enter image description here

(Карта изображения доступны для некоммерческого общественного пользования Wikimedia Commons).

Я думаю, что igraph способен производить такие цифры, но это не основная цель этого программного обеспечения, поэтому у него есть свои ограничения. В какой-то момент вы можете использовать некоторое программное обеспечение Географической информационной системы (GIS), которое предназначено именно для этого. У меня нет опыта с этими, но qgis, вероятно, стоит взглянуть.

+0

Это прекрасно. Отличное решение. Предложение больших кругов было действительно полезно (http://flowingdata.com/2011/05/11/how-to-map-connections-with-great-circles/), чтобы визуально делать то, что мне было нужно. – willemr

Смежные вопросы