Using R, I want to create a ggplot facet chart that includes a zero line (using geom_hline) in each facet having data that straddles the zero line, while excluding the zero line in each facet having exclusively positive or exclusively negative data. Here is a reprex.
library(ggplot)
dfw <- data.frame(
date=c(1,2,3,4,5,6),
A=c(50,53,62,56,54,61),
B=c(-3,-1,5,7,4,-2),
C=c(6,4,5,2,3,-2)
)
dfl <- pivot_longer(dfw,2:4,names_to="nms",values_to="val")
# With no zero line: works fine
ggplot(dfl)
geom_line(aes(x=date,y=val))
facet_wrap(~nms,scales="free_y")
# With zero line for all facets: works fine
ggplot(dfl)
geom_hline(yintercept=0)
geom_line(aes(x=date,y=val))
facet_wrap(~nms,scales="free_y")
# With zero line, but only for facets with some data points greater than zero
# and other data points less than zero: Does not work
c0 <- ggplot(dfl)
geom_line(aes(x=date,y=val))
if (min(y)>0 | max(y)<0) { # Error: object 'y' not found
c0 <- c0 geom_hline(yintercept=0)
}
c0 <- c0 facet_wrap(~nms,scales="free_y")
CodePudding user response:
You can compute y-intercepts for each facet before plotting, setting to 0
if the data includes 0
and NA
otherwise:
library(ggplot2)
library(dplyr)
dfl <- dfl %>%
mutate(
zline = ifelse(min(val) < 0 & max(val > 0), 0, NA),
.by = nms # `.by` argument added in dplyr v1.1.0
)
ggplot(dfl)
geom_hline(aes(yintercept = zline), na.rm = TRUE)
geom_line(aes(x = date, y = val))
facet_wrap(~nms, scales = "free_y")
CodePudding user response:
Here is another solution using a trick:
We say: if all val
are > 0 then color our hline
white (then it will be invisible). The underlying trick is to use I()
. I learned this from @tjebo here