Переливание точек на картах в R (например, с помощью ggplot2) - как сдвинуть точки в сторону, отметить исходные позиции, объединить точки рядом ...?


12

У меня есть база данных, содержащая языки, их долготу и широту и значение элемента (либо категория 1, категория 2 или оба - на графике они обозначены соответственно красным, синим и зеленым). Может быть до трех точек на язык, и, естественно, две языковые точки могут лежать очень близко друг к другу.

    name            longitude   latitude    sp_sum
1   Modern Armenian 45          40          both
2   Modern Armenian 45          40          both
3   Modern Armenian 45          40          spatial
4   Dieri           138         -28.1667    both
5   Dieri           138         -28.1667    both
6   Finnish         25.5577     64.7628     non-spatial
7   Crimean Tatar   28.1418     43.8398     spatial
8   Ese Ejja        -67.515     -11.7268    non-spatial
9   Makhuwa         38.8052     -14.8509    non-spatial
...

Я использую пакет R ggplot2 (это тот, с которым я больше всего знаком, поэтому я был бы рад продолжать его использовать - но другие решения также приветствуются). Вот кадрирование с предыдущей попытки (код: см. Ниже 1 ):

Обрезать с предыдущей попытки

Для каждой точки я хотел бы, чтобы (грубая) позиция - а также значение - все еще были видны. (Если есть несколько точек для одного языка, они могут быть объединены.)

Есть ли способ либо ...

  • ... переместить точки в сторону настолько, чтобы не было переполнения (менее случайно, чем, скажем, с помощью geom_jitter - в пакете beeswarm , например, много таких уклонений )?
  • ... и / или иметь какую-то "линию", указывающую на исходное положение точки, если ее нужно было перемещать?
  • ... или комбинировать точки сближения таким образом, чтобы они все еще были ясны (возможно, существует метод работы, использующий биннинг, то есть stat_bin * или что-то с аналогичным эффектом)?
  • ... или создать "интерактивный сюжет", подобный тем, которые можно увидеть на веб-сайтах, которые все еще можно включить в PDF-файл (я также думаю о возможностях таких пакетов, как анимация и блестящие материалы )? Например, на wals.info это выглядит так :

    Wals

Из предыдущего поста я знаю, что пакет directlabels может перемещать метки, но я также не нашел способа заставить его перемещать точки.

Не стесняйтесь просить разъяснений!

Примечание: я знаю, что было несколько вопросов о перепланировке, но те, которые я изучил, похоже, имеют другую (то есть статистическую) цель (я не утверждаю, что прочитал все это , поэтому я ' Конечно, я тоже буду рад принять ссылку. Я постараюсь перечислить те сообщения, которые я знаю и которые вполне могут быть актуальны (- из того, что я прочитал, ни один из них точно не отвечает на мой вопрос).


1 Следующие строки кода создали обрезку сверху.

library(OpenStreetMap)
library(ggplot2)

data <- read.csv(header = T, sep = ",", dec = ".", quote= "'",
text = "'','name','longitude','latitude','sp_sum'
'1','Modern Armenian',45,40,'both'
'2','Modern Armenian',45,40,'both'
'3','Modern Armenian',45,40,'spatial'
'4','Dieri',138,-28.1667,'both'
'5','Dieri',138,-28.1667,'both'
'6','Finnish',25.5577,64.7628,'non-spatial'
'7','Crimean Tatar',28.1418,43.8398,'spatial'
'8','Sochiapam Chinantec',-96.6079,17.7985,'non-spatial'
'9','Ese Ejja',-67.515,-11.7268,'non-spatial'
'10','Makhuwa',38.8052,-14.8509,'non-spatial'
'11','Mualang',111.077,0.31083,'non-spatial'
'12','Martuthunira',116.607,-20.9294,'non-spatial'
'13','Evenki',108.626,53.85,'both'
'14','Afrikaans',30,-22,'both'
'15','Male (Ethiopia)',36.9892,5.91975,'both'
'16','Manchu',126.557,47.3122,'both'
'17','Dime',36.3329,6.20951,'non-spatial'
'18','Koorete',37.8679,5.80545,'non-spatial'
'19','Wolaytta',37.7537,6.32668,'both'
'20','Dizin',35.5763,6.1405,'both'")

map <- openproj(openmap(c(85, -179.9), c(-60, 179.9), zoom = 2, type = "nps"))
plot <- autoplot(map) + 
  geom_point(data = data, aes(x = longitude, y = latitude),
             color = "white", alpha = 0.8, size = 8) +
  geom_point(data = data, aes(x = longitude, y = latitude, color = sp_sum),
             alpha = 0.3, size = 4)
plot

Что я могу улучшить, чтобы облегчить понимание и ответ на вопрос? Пожалуйста, дайте мне знать, если у вас есть идеи!
майор

1
Это не тот вопрос, с которым у меня есть соответствующие навыки, но я проголосовал за него, чтобы он показался немного выше в некоторых списках. Если вы не получите никаких комментариев, которые помогут улучшить его, и в любом случае, я рекомендую просматривать / пересматривать его через определенные промежутки времени, принимая во внимание рекомендации, предложенные на meta.gis.stackexchange.com/a/3353
PolyGeo

Я думаю, что вы можете использовать некоторые функциональные возможности направленного графа. Я не уверен, как это сделать и сохранить некоторые точки на якоре, но я думаю, чтобы идентифицировать все кластеры (с помощью некоторой функции группировки близости) и использовать центроид кластера в качестве якоря и позволить его членам плавать (а не построение самого центроида - просто используя его для привязки связанных вершин в его маленьком графе). И, конечно, если в каких-либо кластерах есть только один член, они также должны быть привязаны к их местоположению.
aaryno

Я не следовать в стороне на «... опять же, кажется , только применить к диаграммам рассеяния» , потому что это является рассеиванием.
whuber

Я признаю, что, должно быть, я использовал неправильный термин - то, что я хотел сказать под scatterplot, было типичным статистическим scatterplot, где положение, как правило, менее важно, чем в виде графика, который у нас здесь (= карта - если точки перемещаются здесь, это очевидно немедленно).
Май

Ответы:


2

До сих пор я нашел только один достаточно приличный обходной путь: пакет packcircles R, возможно, был разработан для другой цели, но он отлично справляется с отжиманием точек друг от друга (см. Также соответствующее сообщение в блоге ). Возможно, я не понимаю всю внутреннюю работу этого пакета, но, к счастью, как вы увидите, файл примера с веб-сайта можно использовать почти напрямую - все, что нужно изменить, - это имена переменных, расстояние между кругами (или точками). в зависимости от используемых вами функций) и «пределов» графика (т. е. 180 °).

(В конце концов все сводится к circleLayout()функции, которая принимает фрейм данных со столбцами lon, lat и radius (то есть расстояние) и двумя 2-числовыми векторами xlim / ylim - он возвращает фрейм данных с улучшенными позициями точек.)

«Сюжет», который обычно создается с помощью packcircles - вы уже можете видеть, что он работает здесь. карта

  • сравните эту карту «после» с фрагментом карты «до» из вопроса

0

Может быть, как-то так?

data$spacing_x = 5
data$spacing_y = 5

for(i in 2:nrow(data)) {
  if( abs(data$latitude[i]-data$latitude[i+1]) < 2 ) {
    data$spacing_y[i] = data$spacing_y + 6 +jitter(data$spacing_y,8)
    data$spacing_y[i+1] = data$spacing_y + 6 + jitter(data$spacing_y,8)
  }
}

for(i in 2:nrow(data)) {
     if( abs(data$longitude[i]-data$longitude[i+1]) < 2 ) {
      data$spacing_x[i] = data$spacing_x + jitter(data$spacing_x,4)
      data$spacing_x[i+1] = data$spacing_x +jitter(data$spacing_x,4)
     }
}

for(i in 2:nrow(data)) {
  if( abs(data$spacing_y[i]-data$spacing_y[i+1]) < 1.5 ) {
    data$spacing_y[i] = data$spacing_y + 2 
    data$spacing_y[i+1] = data$spacing_y + 2
  }
}

for(i in 2:nrow(data)) {
  if( abs(data$spacing_x[i]-data$spacing_x[i+1]) < 1.5 ) {
    data$spacing_x[i] = data$spacing_x + 2 
    data$spacing_x[i+1] = data$spacing_x + 2
  }
}


plot = autoplot(map) + 
  geom_segment(data = data
               , mapping=aes(x=longitude
                             , y=latitude
                             , xend=longitude + spacing_x
                             , yend=latitude + spacing_y)
               , size=0.5, color="black"
               , alpha = 0.9) +
  geom_point(data = data
             , aes(x = longitude+spacing_x
                  , y = latitude+spacing_y)
             , color = "white"
             , alpha = 0.8, size = 8) +
  geom_point(data = data
             , aes(x = longitude+spacing_x
                   , y = latitude+spacing_y
                   , color = sp_sum)
             , alpha = 0.3, size = 4)
  xlab("") +
  ylab("")
plot

Понимаю. Вы пытались повторить "строки в исходное положение" на скриншоте с wals.info, не так ли? Это начало, я думаю. Но если я вижу это правильно, это не решит большую часть моей проблемы (например, точки все еще пересекаются).
майор

Остальное должно быть манипуляцией с фреймом данных. Цикл if / for может управлять интервалом - в нем также может быть сказано, что если интервал между точками меньше x, пометьте их как таковые и этот маркер можно использовать для объединения точек

Надеюсь, кто-то или вы, можете исправить мои уродливые петли. Удачи.

@InNoam: На самом деле, я открыт для подсказок о том, как может работать эта «манипуляция фреймами данных».
май
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.