2014-01-09 3 views
11

[Edit апреля 2016 года: решение в этой теме больше не отображается добавленная ось правильно - новый поток по этому вопросу была открыта в ggplot2 2.1.0 broke my code? Secondary transformed axis now appears incorrectly]ggplot2: Добавление вторичной трансформированной оси х на верхней части участка

Я работаю с масштабированными данными x, и вам нужно добавить необрезанную ось x в начало графика для упрощения интерпретации. Я столкнулся с подходом для добавления вторичной оси y в How can I put a transformed scale on the right side of a ggplot2?. Однако я не могу заставить его работать правильно для оси x. Я уверен, что не понимаю какую-то часть кода, но я не могу понять, что это такое. Я пробовал искать в файлах справки ggplot2, а также книгу Wickham ggplot2: Элегантная графика для анализа данных, но если кто-нибудь может указать мне на какую-то соответствующую документацию, я бы очень признателен!

Я работаю с данными о температуре, но я буду использовать данные о озере по приведенной выше ссылке, поскольку для этого был написан код. Здесь оригинальный код из этой ссылки:

library(ggplot2) 
library(gtable) 
library(grid) 
LakeLevels<-data.frame(Day=c(1:365),Elevation=sin(seq(0,2*pi,2*pi/364))*10+100) 
p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Day,y=Elevation)) + 
     scale_y_continuous(name="Elevation (m)",limits=c(75,125)) 

p2<-ggplot(data=LakeLevels)+geom_line(aes(x=Day, y=Elevation))+ 
    scale_y_continuous(name="Elevation (ft)", limits=c(75,125),   
    breaks=c(80,90,100,110,120), 
      labels=c("262", "295", "328", "361", "394")) 

#extract gtable 
g1<-ggplot_gtable(ggplot_build(p1)) 
g2<-ggplot_gtable(ggplot_build(p2)) 

#overlap the panel of the 2nd plot on that of the 1st plot 

pp<-c(subset(g1$layout, name=="panel", se=t:r)) 
g<-gtable_add_grob(g1, g2$grobs[[which(g2$layout$name=="panel")]], pp$t, pp$l, pp$b, 
        pp$l) 

ia <- which(g2$layout$name == "axis-l") 
ga <- g2$grobs[[ia]] 
ax <- ga$children[[2]] 
ax$widths <- rev(ax$widths) 
ax$grobs <- rev(ax$grobs) 
ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm") 
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1) 
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b) 

# draw it 
grid.draw(g) 

Для того, чтобы проверить метод для добавления оси х, а не у-оси, я переключил оси х и у и изменил axis-l к axis-b, чтобы дать:

library(ggplot2) 
library(gtable) 
library(grid) 
LakeLevels<-data.frame(Day=c(1:365),Elevation=sin(seq(0,2*pi,2*pi/364))*10+100) 
p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Elevation,y=Day)) + 
scale_x_continuous(name="Elevation (m)",limits=c(75,125)) 

p2<-ggplot(data=LakeLevels)+geom_line(aes(x=Elevation, y=Day))+ 
scale_x_continuous(name="Elevation (ft)", limits=c(75,125),   
        breaks=c(80,90,100,110,120), 
        labels=c("262", "295", "328", "361", "394")) 

#extract gtable 
g1<-ggplot_gtable(ggplot_build(p1)) 
g2<-ggplot_gtable(ggplot_build(p2)) 

#overlap the panel of the 2nd plot on that of the 1st plot 

pp<-c(subset(g1$layout, name=="panel", se=t:r)) 
g<-gtable_add_grob(g1, g2$grobs[[which(g2$layout$name=="panel")]], pp$t, pp$l, pp$b, 
       pp$l) 

ia <- which(g2$layout$name == "axis-b") 
ga <- g2$grobs[[ia]] 
ax <- ga$children[[2]] 
ax$widths <- rev(ax$widths) 
ax$grobs <- rev(ax$grobs) 
ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm") 
g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1) 
g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b) 

# draw it 
grid.draw(g) 

Это создает новую ось х, но есть несколько проблем: 1) находится в середине участка 2) он не производит новую х-метку «Elevation (фут)»

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

Также, как упоминалось выше, я работаю с масштабированными данными температуры, поэтому в идеале тики не будут выравниваться по верхней и нижней осям, как в этом примере. Есть ли способ сделать это в ggplot2? Произвольный пример из Интернета заключается в следующем:

Two x axes with different scales

ответ

14

корень вашей проблемы является то, что вы модифицирующие столбцы и строки не.

Установка с масштабными метками на X-оси второго участка:

## 'base' plot 
p1 <- ggplot(data=LakeLevels) + geom_line(aes(x=Elevation,y=Day)) + 
    scale_x_continuous(name="Elevation (m)",limits=c(75,125)) 

## plot with "transformed" axis 
p2<-ggplot(data=LakeLevels)+geom_line(aes(x=Elevation, y=Day))+ 
    scale_x_continuous(name="Elevation (ft)", limits=c(75,125), 
        breaks=c(90,101,120), 
        labels=round(c(90,101,120)*3.24084) ## labels convert to feet 
        ) 

## extract gtable 
g1 <- ggplot_gtable(ggplot_build(p1)) 
g2 <- ggplot_gtable(ggplot_build(p2)) 

## overlap the panel of the 2nd plot on that of the 1st plot 
pp <- c(subset(g1$layout, name=="panel", se=t:r)) 

g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name=="panel")]], pp$t, pp$l, pp$b, 
       pp$l) 

EDIT, чтобы иметь сетку линий выравнивания с нижней осью клещи, замените эту строку с: g <- gtable_add_grob(g1, g1$grobs[[which(g1$layout$name=="panel")]], pp$t, pp$l, pp$b, pp$l)

## steal axis from second plot and modify 
ia <- which(g2$layout$name == "axis-b") 
ga <- g2$grobs[[ia]] 
ax <- ga$children[[2]] 

Теперь вам необходимо убедиться, что вы изменяете правильное измерение. Поскольку новая ось является горизонтальной (строка, а не столбец), whatever_grob$heights - это вектор для изменения, чтобы изменить количество вертикального пространства в данной строке. Если вы хотите добавить новое пространство, обязательно добавьте строку, а не столбец (например, используйте gtable_add_rows()).

Если вы сами модифицируете гниль (в этом случае мы меняем вертикальное обоснование тиков), обязательно измените y (вертикальное положение), а не x (горизонтальное положение).

## switch position of ticks and labels 
ax$heights <- rev(ax$heights) 
ax$grobs <- rev(ax$grobs) 
ax$grobs[[2]]$y <- ax$grobs[[2]]$y - unit(1, "npc") + unit(0.15, "cm") 

## modify existing row to be tall enough for axis 
g$heights[[2]] <- g$heights[g2$layout[ia,]$t] 

## add new axis 
g <- gtable_add_grob(g, ax, 2, 4, 2, 4) 

## add new row for upper axis label 
g <- gtable_add_rows(g, g2$heights[1], 1) 
g <- gtable_add_grob(g, g2$grob[[6]], 2, 4, 2, 4) 

# draw it 
grid.draw(g) 

Замечу мимоходом, что gtable_show_layout() очень, очень удобная функция для выяснить, что происходит.

+0

Nate Pope, ваше решение работает отлично, но в моих реальных данных две оси масштабируются по-разному, так что данные на каждом графике не перекрываются должным образом. Это означает, что весы немного сбиты, когда я рисую их вместе. Вы знаете какой-либо способ решить эту проблему? – Thomas

+0

Мне удалось решить проблему несогласованности шкалы между осями, предварительно вычислив соответствующий диапазон для каждой оси, а установка использует + scale_x_continuous (пределы = c (x1, x2)). Надеюсь, это кому-то полезно. – Thomas

+0

Я заметил, что линии сетки и данные в полученном графике взяты из новой верхней оси, а не из нижней оси. Есть ли способ использовать линии сетки и данные с нижней оси? – Thomas

Смежные вопросы