在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上看起来像这样:

    沃尔斯

从这里的上一篇文章中,我知道directlabels包可以移动标签,但是我还没有找到一种使它也移动点的方法。

随时要求澄清!

注意:我知道有很多有关过度绘图的问题,但是我研究过的所有问题似乎都有不同的目的(即统计目的)(我不声称已阅读全部内容,因此我d当然也很乐意接受链接)。我将尝试列出我知道并且可能相关的那些帖子(-从我阅读的内容来看,这些都不能完全回答我的问题。)


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 2015年

我并没有在“ ...似乎又只适用于散点图”这一点上作废,因为这一个散点图。
ub

我承认我一定使用了错误的术语- 散点图是我想说的是典型的统计散点图,其中位置通常不如我们在此处使用的那种绘图重要(=地图-如果将点移到此处,很明显立即)。
2015年

Answers:


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循环可以控制间距-语句也可以说,如果to点之间的间距小于x,则将它们标记为x,并且可以使用标记来连接这些点

希望有人或您可以修复我的丑陋循环。祝好运。

@InNoam:实际上,我对这种“数据帧操纵”如何工作的暗示持开放态度。
少校
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.