2012-11-17 2 views
16

모양과 색상을 나타내는 두 개의 범례 (아래 예제에서 "Type"과 "Org")가있는지도를 만들고 범례가 삽입되어 있습니다. 전설을 배치 할 수는 있지만 왼쪽 가장자리가 정렬되도록 왼쪽 정렬 할 것을 권한다. 나는 서로에 대해 중심 이외의 그 어떤 것도 할 수 없습니다 :ggmap/ggplot2에서 여러 범례의 양쪽 정렬

require(ggplot2) 
require(ggmap) 
require(grid) 
require(mapproj) 

data <- data.frame(Org=rep(c("ABCDEFG","HIJKLMNOP","QRSTUVWX"),4) 
        , Type=rep(c("Y","Z"),6), Lat=runif(12,48,54.5) 
        , Long=runif(12,-133.5,-122.5)) 

osmMap <- get_map(location=c(-134,47.5,-122,55), source = 'osm') 

points <- geom_jitter(data=data, aes(Long, Lat, shape=Type 
            , colour=Org)) 

legend <- theme(legend.justification=c(0,0), legend.position=c(0,0) 
       , legend.margin=unit(0,"lines"), legend.box="vertical" 
       , legend.key.size=unit(1,"lines"), legend.text.align=0 
       , legend.title.align=0) 

ggmap(osmMap) + points + legend 

enter image description here

+1

하지만 당신은 조금 속이 수 있습니다뿐만 아니라 더 복잡한 경우 즉, 두 전설을 가진 경우 폭의 차이 2. 변경된 계산, 이제 코드는 예를 들어, 작업을해야 형식을 사용하여 같은 크기로 만듭니다. 데이터 선언 다음에'data $ Type <- format (data $ Type, width = 17)'을 시도하고 코드를 다시 실행하십시오. –

+0

그건 멋진 트릭이에요. 고마워요. 나는 월요일에 그것에게 총을 줄 것이다 – andyteucher

답변

19

이 옵션은 ggplot2 0.9.3.1에서 사용할 수 있습니다 사용

ggmap(osmMap) + points + legend + theme(legend.box.just = "left") 

이전, 수동 솔루션 :

여기 해결책이 있습니다.

require(gtable) 
require(ggplot2) 
require(ggmap) 
require(grid) 
require(mapproj) 

# Original data 
data <- data.frame(Org=rep(c("ABCDEFG","HIJKLMNOP","QRSTUVWX"),4), 
        Type=rep(c("Y","Z"),6), Lat=runif(12,48,54.5), 
        Long=runif(12,-133.5,-122.5)) 
osmMap <- get_map(location=c(-134,47.5,-122,55), source = 'google') 
points <- geom_jitter(data=data, aes(Long, Lat, shape=Type, colour=Org)) 
legend <- theme(legend.justification=c(0,0), legend.position=c(0,0), 
       legend.margin=unit(0,"lines"), legend.box="vertical", 
       legend.key.size=unit(1,"lines"), legend.text.align=0, 
       legend.title.align=0) 

# Data transformation 
p <- ggmap(osmMap) + points + legend 
data <- ggplot_build(p) 
gtable <- ggplot_gtable(data) 

# Determining index of legends table 
lbox <- which(sapply(gtable$grobs, paste) == "gtable[guide-box]") 
# Each legend has several parts, wdth contains total widths for each legend 
wdth <- with(gtable$grobs[[lbox]], c(sum(as.vector(grobs[[1]]$widths)), 
            sum(as.vector(grobs[[2]]$widths)))) 
# Determining narrower legend 
id <- which.min(wdth) 
# Adding a new empty column of abs(diff(wdth)) mm width on the right of 
# the smaller legend box 
gtable$grobs[[lbox]]$grobs[[id]] <- gtable_add_cols(
             gtable$grobs[[lbox]]$grobs[[id]], 
             unit(abs(diff(wdth)), "mm")) 
# Plotting 
grid.draw(gtable) 

이것은 Type 또는 Org에 의존하지 않습니다. 그러나 이것은 2 가지 이상의 전설을 갖는 것만으로는 충분하지 않습니다. 또한 grobs (그래픽 개체) 목록이 변경되도록 일부 변경을 수행하는 경우 grobs[[8]]grobs[[i]]으로 변경해야 할 수도 있습니다. 은 범례의 위치이며 gtable$grobs을 참조하고 TableGrob (5 x 3) "guide-box": 2 grobs을 찾으십시오. enter image description here

편집 : 1. 자동 그래프의 다른 부분을 수정 한 후 아무 변경 GROB 전설 인 테이블, 즉 필요를 검출하지 않는다. 이것은 직접 대답하지

enter image description here

+0

@ Julius에게 감사한다 - 이것은 잘 작동하고, 내가 전에 정말로 탐구하지 않았던 gtable을 사용함에 대한 약간의 통찰력을 주었다. – andyteucher

+0

이 예제를 재현 할 수 없습니다. 어디서'osmMap'을 얻을 수 있습니까? 나는 이것이 어떤 데이터 세트라고 가정한다. –

+1

@FaheemMitha, 네, 그 질문의 데이터입니다. 나는 그것을 내 답변에 추가했고,'source = 'osm'을'source = 'google'로 변경했다. 왜냐하면 전자는 적어도 현재는 작동하지 않기 때문이다. – Julius