Como posso colocar uma escala transformada no lado direito de um ggplot2?

Estou criando um gráfico mostrando a mudança nos níveis do lago ao longo do tempo. Anexei um exemplo simples abaixo. Gostaria de adicionar uma escala (marcas de escala e anotação) no lado direito do gráfico que mostra a elevação em pés. Eu sei que o ggplot2 não permite duas escalas diferentes (veja Gráfico com dois eixos y, um eixo y à esquerda e outro eixo y à direita ), mas porque isso é uma transformação da mesma escala, existe uma maneira de faça isso? Eu preferiria continuar usando ggplot2 e não ter que reverter para a function plot ().

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

Você deve dar uma olhada neste link http://rpubs.com/kohske/dual_axis_in_ggplot2 .

Eu adaptei o código fornecido para o seu exemplo. Essa correção parece muito “hacky”, mas faz com que você faça parte do caminho. A única peça que resta é descobrir como adicionar texto ao eixo direito do gráfico.

  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) 

insira a descrição da imagem aqui

Eu poderia ter encontrado uma solução para colocar o título do eixo, com algumas idéias da resposta de Nate Pope que podem ser encontradas aqui:
ggplot2: Adicionando o eixo x transformado secundário no topo da plotagem
E uma discussão sobre como acessar os grobs no gtable aqui: https://groups.google.com/forum/m/#!topic/ggplot2-dev/AVHHcYqc5uU

No final, acabei de adicionar a linha

 g < - gtable_add_grob(g, g2$grob[[7]], pp$t, length(g$widths), pp$b) 

antes de chamar grid.draw(g) , que parecia fazer o truque.
Pelo que entendi, ele pega o título do eixo y g2$grob[[7]] e o coloca no lado mais externo da direita. Pode não ser a solução perfeita, mas funcionou para mim.

Uma última coisa. Seria bom encontrar uma maneira de girar o título do eixo.

Saudações,

Tim

Esta questão foi respondida, mas o problema geral de adicionar um eixo secundário e uma escala secundária ao lado direito de um object ggplot é aquele que surge o tempo todo. Gostaria de relatar abaixo o meu próprio ajuste sobre o problema, com base em vários elementos dados por várias respostas neste segmento, bem como em vários outros tópicos (consulte uma lista parcial de referências abaixo).

Eu tenho uma necessidade de produção em massa de charts de eixo duplo, então eu construí uma function ggplot_dual_axis() . Aqui estão as características de interesse potencial:

  1. O código exibe linhas de grade para os eixos y-left e y-right (essa é minha principal contribuição, embora seja trivial)

  2. O código imprime um símbolo do euro e o incorpora no pdf (algo que vi lá: Plotando o símbolo Euro em ggplot2? )

  3. O código tenta evitar a impressão de determinados elementos duas vezes (‘tentativas’ sugerem que duvido que seja bem-sucedida)

Perguntas não respondidas:

  • Existe uma maneira de modificar a function ggplot_dual_axis() para remover um dos geom_line() ou geom_point() ou o que quer que seja sem lançar erros se esses elementos geométricos não estiverem presentes. No pseudo-código algo como if has(geom_line) ...

  • Como posso chamar o g2$grobs[[7]] por palavra-chave em vez de indexar? Isto é o que ele retorna: text[axis.title.y.text.232] Meu interesse na questão vem das minhas tentativas fracassadas de pegar as linhas de grade aplicando um truque similar. Eu acho que as linhas de grade estão escondidas em algum lugar dentro de g2$grobs[[4]] , mas eu não tenho certeza de como acessá-las.

Editar Pergunta Pude responder a mim mesmo: Como posso aumentar a margem do gráfico no lado direito, onde está o label ‘Euro’? Resposta: theme(plot.margin = unit(c(1,3,0.5,0.8), "lines")) fará o truque, por exemplo.

Por favor, indique quaisquer problemas óbvios ou sugira melhorias.

Agora o código: espero que seja útil para alguém. Como eu disse, eu não reivindico originalidade, é uma combinação de coisas que os outros já mostraram.

 ##' function named ggplot_dual_axis() ##' Takes 2 ggplot plots and makes a dual y-axis plot ##' function takes 2 compulsory arguments and 1 optional argument ##' arg lhs is the ggplot whose y-axis is to be displayed on the left ##' arg rhs is the ggplot whose y-axis is to be displayed on the right ##' arg 'axis.title.y.rhs' takes value "rotate" to rotate right y-axis label ##' The function does as little as possible, namely: ##' # display the lhs plot without minor grid lines and with a ##' transparent background to allow grid lines to show ##' # display the rhs plot without minor grid lines and with a ##' secondary y axis, a rotated axis label, without minor grid lines ##' # justify the y-axis label by setting 'hjust = 0' in 'axis.text.y' ##' # rotate the right plot 'axis.title.y' by 270 degrees, for symmetry ##' # rotation can be turned off with 'axis.title.y.rhs' option ##' ggplot_dual_axis < - function(lhs, rhs, axis.title.y.rhs = "rotate") { # 1. Fix the right y-axis label justification rhs <- rhs + theme(axis.text.y = element_text(hjust = 0)) # 2. Rotate the right y-axis label by 270 degrees by default if (missing(axis.title.y.rhs) | axis.title.y.rhs %in% c("rotate", "rotated")) { rhs <- rhs + theme(axis.title.y = element_text(angle = 270)) } # 3a. Use only major grid lines for the left axis lhs <- lhs + theme(panel.grid.minor = element_blank()) # 3b. Use only major grid lines for the right axis # force transparency of the backgrounds to allow grid lines to show rhs <- rhs + theme(panel.grid.minor = element_blank(), panel.background = element_rect(fill = "transparent", colour = NA), plot.background = element_rect(fill = "transparent", colour = NA)) # Process gtable objects # 4. Extract gtable library("gtable") # loads the grid package g1 <- ggplot_gtable(ggplot_build(lhs)) g2 <- ggplot_gtable(ggplot_build(rhs)) # 5. Overlap the panel of the rhs plot on that of the lhs 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) # Tweak axis position and labels ia <- which(g2$layout$name == "axis-l") ga <- g2$grobs[[ia]] ax <- ga$children[["axis"]] # 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) g <- gtable_add_grob(g, g2$grobs[[7]], pp$t, length(g$widths), pp$b) # Display plot with arrangeGrob wrapper arrangeGrob(g) library("gridExtra") grid.newpage() return(arrangeGrob(g)) } 

E abaixo de alguns dados falsos e duas plots que se destinam a ser em unidades de dólar e euro. Não seria legal ter um pacote que permitisse fazer um gráfico e envolvê-lo em uma chamada para um gráfico de eixo duplo como ggplot_dual_axis_er(ggplot_object, currency = c("dollar", "euro")) e buscaria automaticamente as taxas de câmbio para você! 🙂

 # Set directory: if(.Platform$OS.type == "windows"){ setwd("c:/R/plots") } else { setwd("~/R/plots") } # Load libraries library("ggplot2") library("scales") # Create euro currency symbol in plot labels, simple version # avoids loading multiple libraries # avoids problems with rounding of small numbers, eg .0001 labels_euro < - function(x) {# no rounding paste0("€", format(x, big.mark = ",", decimal.mark = ".", trim = TRUE, scientific = FALSE)) } labels_dollar <- function(x) {# no rounding: overwrites dollar() of library scales paste0("$", format(x, big.mark = ",", decimal.mark = ".", trim = TRUE, scientific = FALSE)) } # Create data df <- data.frame( Year = as.Date(c("2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018"), "%Y"), Dollar = c(0, 9000000, 1000000, 8000000, 2000000, 7000000, 3000000, 6000000, 4000000, 5000000, 5000000, 6000000, 4000000, 7000000, 300000, 8000000, 2000000, 9000000)) # set Euro/Dollar exchange rate at 0.8 euros = 1 dollar df <- cbind(df, Euro = 0.8 * df$Dollar) # Left y-axis p1 <- ggplot(data = df, aes(x = Year, y = Dollar)) + geom_line(linestyle = "blank") + # manually remove the line theme_bw(20) + # make sure font sizes match in both plots scale_x_date(labels = date_format("%Y"), breaks = date_breaks("2 years")) + scale_y_continuous(labels = labels_dollar, breaks = seq(from = 0, to = 8000000, by = 2000000)) # Right y-axis p2 <- ggplot(data = df, aes(x = Year, y = Euro)) + geom_line(color = "blue", linestyle = "dotted", size = 1) + xlab(NULL) + # manually remove the label theme_bw(20) + # make sure font sizes match in both plots scale_x_date(labels = date_format("%Y"), breaks = date_breaks("2 years")) + scale_y_continuous(labels = labels_euro, breaks = seq(from = 0, to = 7000000, by = 2000000)) # Combine left y-axis with right y-axis p <- ggplot_dual_axis(lhs = p1, rhs = p2) p # Save to PDF pdf("ggplot-dual-axis-function-test.pdf", encoding = "ISOLatin9.enc", width = 12, height = 8) p dev.off() embedFonts(file = "ggplot-dual-axis-function-test.pdf", outfile = "ggplot-dual-axis-function-test-embedded.pdf") 

insira a descrição da imagem aqui

Lista parcial de referências:

  1. Exibe dois eixos paralelos em um ggplot (R)
  2. Eixo y duplo em ggplot2 para várias figuras de painel
  3. Como posso colocar uma escala transformada no lado direito de um ggplot2?
  4. Preservar a proporção de charts usando grid.arrange
  5. Os perigos de alinhar charts em ggplot
  6. https://github.com/kohske/ggplot2

Para rotacionar o título do eixo, adicione o seguinte ao gráfico p2:

 p2 < - p2 + theme(axis.title.y=element_text(angle=270))