Is there a ggplot2 form to “reverse” only one axis

2020-08-01 06:06发布

问题:

I'm trying to plot a two "y" axis, the first one with "soil water content" in % (geom_line() ) and a geom_bar() with precipitation data. The problem is the precipitation chart. I need to "reverse" the plot.

I have this chart now:

and I need the soil water content time series as image above but precipitation as following image

Transforming the data do not solve the problem since i can not transform the bar plot for visualize it form upside down since the data are bars not points. Overmore when i reverse the plot both axis turn reverse

the "hum_melt10" data frame is a data frame with 3 columns: fecha = date (daily), value = water content (%) and variable = if the data is from a probe o from a model

the "pp_melt" data frame is a data frame with 3 columns: fecha = date (daily), value = cm of precipitation for each day and variable = if the water is from precipitation or irrigation

gpp = ggplot() +
  geom_line(data = hum_melt10,aes(x = fecha, y = value, color = variable), size = 1.0) + 
  xlab("Fecha") +
  geom_bar(data = pp_melt, aes(x = fecha, y = value / 20, fill  = variable), stat="identity",position = 'dodge', na.rm = TRUE) +
  scale_y_continuous(name = "Contenido de agua (%)",sec.axis = sec_axis(~.*20, name = "pp y riego (cm)")) + 
  scale_x_date(breaks = '2 month', labels = fecha, date_labels = '%b %y') +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 20)) +
  theme_bw() + theme( panel.grid.major = element_blank(),
                      panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), aspect.ratio = 0.3) 

Thank you!

回答1:

Agreeing with @dmp, the use of sec_axis only adds the labels to the right; if you want to flip how it looks in the plot, you need to either

  1. Use scale_y_reverse(), which will flip everything;
  2. Manually flip the series in the aesthetic; or
  3. Manually flip the series in the data itself.

Since you only want to reverse one of the data series and not all of them, #1 is out. #3 does work, though you'll still need to modify the call to sec_axis, so I'll keep it simple with doing just #2.

library(ggplot2)
mt <- transform(mtcars, rn = 1:nrow(mtcars))
ggplot(mt) +
  geom_bar(aes(x = rn, y = drat), stat = "identity") +
  geom_line(aes(x = rn, y = disp/100), stat = "identity", color = "red", size = 1) +
  scale_y_continuous(sec.axis = sec_axis(~ . * 100))

Flipping just the red line, we change both how it is defined in the aesthetic (though it could be changed in the frame itself) and sec_axis.

ggplot(mt) +
  geom_bar(aes(x = rn, y = drat), stat = "identity") +
  geom_line(aes(x = rn, y = 5 - disp/100), stat = "identity", color = "red", size = 1) +
  # changes:                ^^^             vvv
  scale_y_continuous(sec.axis = sec_axis(~ (5 - .) * 100))

(It's important to remember that the flipping point (5 in the example above) is based on the main-axis scale, not the new data.)

Without testing, I suspect the fix for your code would be something like this (where 9 is inferred from the plot).

gpp = ggplot() +
  geom_line(data = hum_melt10,aes(x = fecha, y = value, color = variable), size = 1.0) + 
  xlab("Fecha") +
  geom_bar(data = pp_melt, aes(x = fecha, y = 9 - value / 20, fill  = variable), stat="identity",position = 'dodge', na.rm = TRUE) +
  #  changes:                                 ^^^                          vvv
  scale_y_continuous(name = "Contenido de agua (%)", sec.axis = sec_axis(~(9 - .)*20, name = "pp y riego (cm)")) + 
  scale_x_date(breaks = '2 month', labels = fecha, date_labels = '%b %y') +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 20)) +
  theme_bw() + theme( panel.grid.major = element_blank(),
                     panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), aspect.ratio = 0.3)