2015-05-11 31 views
5

Ggmap paketi R ile çalışıyorum ve coğrafi veri görselleştirmelerinde göreceli olarak yeniyim. Her birinde bir etiket bulunan bir harita üzerinde çizmek istediğim on bir enlem ve boylam çiftinden oluşan bir veri çerçevem ​​var. Aşağıda, model veridir: Şimdi veri noktası etiketleri oluşturmak ve bir harita üzerinde bu çizmek için annotate kullanmakDinamik veri noktası etiketi ggmap uygulamasında konumlandırma

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) 

;

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 

Bu Gördüğünüz gibi, etrafında (-122.44,47.63) üst üste iki veri nokta vardır veri noktaları plot of data points with labels

bir arsa üretir ve bunların etiketler de örtüşmektedir. Artık etiketlerin üst üste gelmesini engellemek için her etiket noktasına manuel olarak bir geçiş ekleyebilirim (bkz. this post), fakat bu farklı bir dizi enlem ve boylam çifti için bu grafiklerin çoğunu üretmem gerektiğinde bu harika bir teknik değildir.

Veri etiketlerini otomatik olarak örtüştürmemin bir yolu var mı? Etiketlerin örtüşüp örtüşmediğinin gerçek rakam büyüklüğüne bağlı olup olmadığını anlıyorum, bu yüzden gerekirse, boyutların belirli boyutlarda sabitlenmesini sağlıyorum. Herhangi bir anlayış için şimdiden teşekkür ederiz!

DÜZENLEME

arsa oluşturuluyor 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 
    })) 
} 

verdiği cevabı kullanarak kod değiştirilir aşağıdadır:

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")) 

ggmap plot with labels within text boxes

Bu KADAR olduğunu daha fazla r eadable arsa, ama olağanüstü bir sorun ile. "Site 1E" etiketinin "Site 1A" ile ilişkili veri noktasını çakışmaya başladığını unutmayın. Yönlendirmeler, başka bir etikete ait veri noktalarının üst üste geldiği etiketlerle uğraşırken bir yolu var mı?

Bununla ilgili son bir soru, bu yöntemi kullanarak birkaç yinelenen etiketi nasıl çizebilirim. Etiketleri varsayalım data.frame içindir hepsi aynı: Ben aynı kodu kullandığınızda

df$labels<-rep("test",dim(df)[1]) 

, directlabels yinelenen etiket adlarını kaldırır: enter image description here

Ama bir etikete sahip her veri noktasını istiyorum "Ölçek". Baska öneri?

cevap

5

Düzenleme 11 Ocak 2016: ggplot2 v2.0.0 ve ggmap v2.6 de

ggrepel eserleri ile ggrepel paketini kullanarak. Aşağıdaki kodda, geom_label_repel() mevcut parametrelerin bir kısmını gösterir.

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) 

enter image description here



Orijinal cevap ama ggplot v2.0.0 ve ggmap v2.6 için güncellenmiş

örtüşen noktaları sadece az sayıda, daha sonra varsa Doğrudan etiket paketinden "top.bumpup" veya "top.bumptwice" yöntemini kullanarak bunları ayırabilirsiniz. Aşağıdaki kodda, etiketleri oluşturmak ve konumlandırmak için geom_dl() işlevini kullanıyorum.

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")) 

enter image description here

Düzenleme: altta yatan etiket

akla yöntemler bahar Birkaç için ayarlanması, ancak hiçbiri tamamen tatmin edicidir. Ancak, tüm durumlara uygulanacak bir çözüm bulacağınızı düşünmüyorum. her bir etiket
Bu bir arka plan rengi ekleme

bir çözüm biraz, fakat directlabels (yani, etiket bir kutuya yerleştirilir) bir "kutu" işlevi vardır. Arka plan dolgusunu ve kenarlık rengini geom_dl listesinde değiştirebilmeli gibi görünüyor, ancak çalışmasını alamıyorum. Bunun yerine, directlabels website'dan iki işlevi (draw.rects ve enlarge.box) aldım; onları değiştir; ve değiştirilmiş işlevleri "top.bumptwice" yöntemiyle birleştirin. o directlabels için nasıl kullanıldığını hemen belli olmasa da

enter image description here

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")) 

, her bir etiket Başka bir seçenek, her etiket bir taslağını vermek için this method kullanmaktır

için bir taslak ekleyin. Bu nedenle, koordinatların manuel olarak ayarlanması veya belirli bir eşiğin içindeki koordinatlar için veri aramasının aranması ve ardından ayarlanması gerekir. Ancak burada, etiketleri konumlandırmak için maptools paketinden pointLabel işlevini kullanıyorum. Her seferinde çalışacağına dair bir garanti yok, ancak verileriniz ile makul bir sonuç aldım. İçinde rastgele bir öğe var, bu yüzden makul bir sonuç elde edene kadar birkaç kez çalıştırabilirsiniz. Ayrıca, etiketleri bir temel çizimde konumlandırdığını unutmayın. Etiket yerleri daha sonra ggplot/ggmap içine alınmalı ve yüklenmelidir.

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) 

enter image description here

+0

directlabels paketi için harika bir araçtır. Öneri için teşekkürler. Listenin kullanımı (dl.trans (y = y + 0.2) ', burada hala geom_dl . 'un işlevselliğini kullanırken etiket konumlarının kontrolünü elinde bulundurmaktaydı. Bu site" Site 1A "'nın dışında mükemmel olurdu. Etiketin altında "Seattle" sözcüğü ile örtüşüyor Bunun için bir çözüm üzerinde herhangi bir öneriniz en değerli olacaktı – Archimeow

+0

@JMeo, Bir düzenleme ekledim –

+0

Mükemmel çözümünüzü kullanarak kodu düzenledim.Metin kutularının herhangi bir komşu veri noktasının üst üste gelmesini ve farklı veri noktaları arasında yinelenen etiketleri nasıl düzenleyeceğiyle ilgili sorularımı (lütfen düzenlemelerim) yaptım. Benimle iletişim kurduğunuz için teşekkür ederim, ben 'directlabels' – Archimeow

İlgili konular