我正在使用R中的ggmap包,我对地理空间数据可视化相对较新.我有一个11个纬度和经度对的数据框,我想在地图上绘制,每个都有一个标签.这是虚拟数据:
lat<- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071,47.586349,47.512684,47.571232,47.562283)
lon<-c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117,-122.368462,-122.331734,-122.294395,-122.33606,-122.379745)
labels<-c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D","Site 2C","Site 1E","Site 2B","Site 1G","Site 2G")
df<-data.frame(lat,lon,labels)
Run Code Online (Sandbox Code Playgroud)
现在我annotate用来创建数据点标签并在地图上绘制这些标签;
map.data <- get_map(location = c(lon=-122.3485,lat=47.6200),
maptype = 'roadmap', zoom = 11)
pointLabels<-annotate("text",x=uniqueReach$lon,y=c(uniqueReach$lat),size=5,font=3,fontface="bold",family="Helvetica",label=as.vector(uniqueReach$label))
dataPlot <- ggmap(map.data) +
geom_point(data = uniqueReach,aes(x = df$lon, y = df$lat), alpha = 1,fill="red",pch=21,size = 6) + labs(x = 'Longitude', y = 'Latitude')+pointLabels
Run Code Online (Sandbox Code Playgroud)
这产生了数据点的图 
如您所见,有两个数据点重叠(-122.44,47.63),它们的标签也重叠.现在我可以手动为每个标签点添加一个移位以防止标签重叠(参见这篇文章),但是当我需要为不同的纬度和经度对产生许多这些图时,这不是一个很好的技术.
有没有办法可以自动保持数据标签不重叠?我意识到标签是否重叠取决于实际的图形尺寸,因此如果需要,我可以将图形尺寸固定在某些尺寸上.提前感谢您的任何见解!
编辑
以下是使用Sandy Mupratt给出的答案修改的代码
# Defining function to draw text boxes
draw.rects.modified <- function(d,...){
if(is.null(d$box.color))d$box.color <- NA
if(is.null(d$fill))d$fill <- "grey95"
for(i in 1:nrow(d)){
with(d[i,],{
grid.rect(gp = gpar(col = box.color, fill = fill,alpha=0.7),
vp = viewport(x, y, w, h, "cm", c(hjust, vjust=0.25), angle=rot))
})
}
d
}
# Defining function to determine text box borders
enlarge.box.modified <- function(d,...){
if(!"h"%in%names(d))stop("need to have already calculated height and width.")
calc.borders(within(d,{
w <- 0.9*w
h <- 1.1*h
}))
}
Run Code Online (Sandbox Code Playgroud)
生成情节:
dataplot<-ggmap(map.data) +
geom_point(data = df,aes(x = df$lon, y = df$lat),
alpha = 1, fill = "red", pch = 21, size = 6) +
labs(x = 'Longitude', y = 'Latitude') +
geom_dl(data = df,
aes(label = labels),
list(dl.trans(y = y + 0.3), "boxes", cex = .8, fontface = "bold"))
Run Code Online (Sandbox Code Playgroud)

这是一个更具可读性的情节,但有一个突出的问题.您会注意到标签"Site 1E"开始与"Site 1A"相关的数据点重叠.直接标签是否有办法处理与属于另一个标签的数据点重叠的标签?
我对此的最后一个问题是如何使用此方法绘制多个重复标签.假设data.frame的标签都是相同的:
df$labels<-rep("test",dim(df)[1])
Run Code Online (Sandbox Code Playgroud)
当我使用相同的代码时,directlabels删除重复的标签名称:

但我希望每个数据点都有一个"测试"标签.有什么建议?
编辑2016年1月11日:使用ggrepel包与ggplot2v2.0.0和ggmapv2.6
ggrepel效果很好.在下面的代码中,geom_label_repel()显示了一些可用的参数.
lat <- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071,
47.586349,47.512684,47.571232,47.562283)
lon <- c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117,
-122.368462,-122.331734,-122.294395,-122.33606,-122.379745)
labels <- c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D",
"Site 2C","Site 1E","Site 2B","Site 1G","Site 2G")
df <- data.frame(lat,lon,labels)
library(ggmap)
library(ggrepel)
library(grid)
map.data <- get_map(location = c(lon = -122.3485, lat = 47.6200),
maptype = 'roadmap', zoom = 11)
ggmap(map.data) +
geom_point(data = df, aes(x = lon, y = lat),
alpha = 1, fill = "red", pch = 21, size = 5) +
labs(x = 'Longitude', y = 'Latitude') +
geom_label_repel(data = df, aes(x = lon, y = lat, label = labels),
fill = "white", box.padding = unit(.4, "lines"),
label.padding = unit(.15, "lines"),
segment.color = "red", segment.size = 1)
Run Code Online (Sandbox Code Playgroud)
原始答案,但已针对ggplotv2.0.0和ggmapv2.6进行了更新
如果只有少量重叠点,那么使用直接标签包中的"top.bumpup"或"top.bumptwice"方法可以将它们分开.在下面的代码中,我使用该geom_dl()函数来创建和定位标签.
lat <- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071,
47.586349,47.512684,47.571232,47.562283)
lon <- c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117,
-122.368462,-122.331734,-122.294395,-122.33606,-122.379745)
labels <- c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D",
"Site 2C","Site 1E","Site 2B","Site 1G","Site 2G")
df <- data.frame(lat,lon,labels)
library(ggmap)
library(directlabels)
map.data <- get_map(location = c(lon = -122.3485, lat = 47.6200),
maptype = 'roadmap', zoom = 11)
ggmap(map.data) +
geom_point(data = df, aes(x = lon, y = lat),
alpha = 1, fill = "red", pch = 21, size = 6) +
labs(x = 'Longitude', y = 'Latitude') +
geom_dl(data = df, aes(label = labels), method = list(dl.trans(y = y + 0.2),
"top.bumptwice", cex = .8, fontface = "bold", family = "Helvetica"))
Run Code Online (Sandbox Code Playgroud)

编辑:调整底层标签
我想到了几种方法,但两种方法都不尽如人意.但我认为您不会找到适用于所有情况的解决方案.
为每个标签添加背景颜色
这是一种解决方法,但directlabels具有"框"功能(即,标签放在框内).看起来应该能够修改列表中的背景填充和边框颜色geom_dl,但我无法使其工作.相反,我从directlabels网站获取两个函数(draw.rects和enlarge.box); 修改它们; 并将修改后的函数与"top.bumptwice"方法结合起来.
draw.rects.modified <- function(d,...){
if(is.null(d$box.color))d$box.color <- NA
if(is.null(d$fill))d$fill <- "grey95"
for(i in 1:nrow(d)){
with(d[i,],{
grid.rect(gp = gpar(col = box.color, fill = fill),
vp = viewport(x, y, w, h, "cm", c(hjust, vjust=0.25), angle=rot))
})
}
d
}
enlarge.box.modified <- function(d,...){
if(!"h"%in%names(d))stop("need to have already calculated height and width.")
calc.borders(within(d,{
w <- 0.9*w
h <- 1.1*h
}))
}
boxes <-
list("top.bumptwice", "calc.boxes", "enlarge.box.modified", "draw.rects.modified")
ggmap(map.data) +
geom_point(data = df,aes(x = lon, y = lat),
alpha = 1, fill = "red", pch = 21, size = 6) +
labs(x = 'Longitude', y = 'Latitude') +
geom_dl(data = df, aes(label = labels), method = list(dl.trans(y = y + 0.3),
"boxes", cex = .8, fontface = "bold"))
Run Code Online (Sandbox Code Playgroud)

为每个标签添加一个轮廓
另一个选择是使用此方法为每个标签赋予一个轮廓,尽管目前还不清楚它如何与直接标签一起使用.因此,需要手动调整坐标,或者搜索数据帧以查找给定阈值内的坐标然后进行调整.但是,在这里,我使用包中的pointLabel函数maptools来定位标签.不保证每次都能正常工作,但我的数据得到了合理的结果.内置了一个随机元素,因此您可以运行它几次,直到获得合理的结果.另请注意,它将标签定位在基础图中.然后必须提取标签位置并将其加载到ggplot/ggmap中.
lat<- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071,47.586349,47.512684,47.571232,47.562283)
lon<-c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117,-122.368462,-122.331734,-122.294395,-122.33606,-122.379745)
labels<-c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D","Site 2C","Site 1E","Site 2B","Site 1G","Site 2G")
df<-data.frame(lat,lon,labels)
library(ggmap)
library(maptools) # pointLabel function
# Get map
map.data <- get_map(location = c(lon=-122.3485,lat=47.6200),
maptype = 'roadmap', zoom = 11)
bb = t(attr(map.data, "bb")) # the map's bounding box
# Base plot to plot points and using pointLabels() to position labels
plot(df$lon, df$lat, pch = 20, cex = 5, col = "red", xlim = bb[c(2,4)], ylim = bb[c(1,3)])
new = pointLabel(df$lon, df$lat, df$labels, pos = 4, offset = 0.5, cex = 1)
new = as.data.frame(new)
new$labels = df$labels
## Draw the map
map = ggmap(map.data) +
geom_point(data = df, aes(x = lon, y = lat),
alpha = 1, fill = "red", pch = 21, size = 5) +
labs(x = 'Longitude', y = 'Latitude')
## Draw the label outlines
theta <- seq(pi/16, 2*pi, length.out=32)
xo <- diff(bb[c(2,4)])/400
yo <- diff(bb[c(1,3)])/400
for(i in theta) {
map <- map + geom_text(data = new,
aes_(x = new$x + .01 + cos(i) * xo, y = new$y + sin(i) * yo, label = labels),
size = 3, colour = 'black', vjust = .5, hjust = .8)
}
# Draw the labels
map +
geom_text(data = new, aes(x = x + .01, y = y, label=labels),
size = 3, colour = 'white', vjust = .5, hjust = .8)
Run Code Online (Sandbox Code Playgroud)

| 归档时间: |
|
| 查看次数: |
5142 次 |
| 最近记录: |