Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to set limits on rounded facet wrap y axis?

Tags:

r

ggplot2

facet

I have this plot and I need to round the y axis so what appears is acceptable EXCEPT for the fact that I would like to not just show 1 value on the y axis. I'd like to add the "limit" to the "scale_y_continuous" function so that the limits for each facet plot are unique to the individual facet.

here is the plot only showing 60 and 80 on the y axis

dat = data.frame(x = c(1,2,3,1,2,3),A=c(80.6, 82,83,60,61,62),A_up =c(81,84,85,62,63,64), A_low =c(79,78,81,59,58,57), group = c("z","z","z","y","y","y"))
ggplot(data=dat , aes(x=as.factor(x), y=A, group = 1)) + #, color =Group, group = Group 
  geom_line()  + geom_point() + # facet_wrap(~COUNTERPARTY_STRATEGY ,ncol=2)
  geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
     scale_y_continuous(breaks = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                      labels = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 )
                      ) +
    facet_wrap(~group ,ncol=2, scales = "free_y") 

Now I add the limit in the scale y continuous and it applies the limit globally.

dat = data.frame(x = c(1,2,3,1,2,3),A=c(80.6, 82,83,60,61,62),A_up =c(81,84,85,62,63,64), A_low =c(79,78,81,59,58,57), group = c("z","z","z","y","y","y"))
ggplot(data=dat , aes(x=as.factor(x), y=A, group = 1)) + #, color =Group, group = Group 
  geom_line()  + geom_point() + # facet_wrap(~COUNTERPARTY_STRATEGY ,ncol=2)
  geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
     scale_y_continuous(breaks = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                      labels = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                   ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                     # limits =  c( floor(  min(dat$A_low[dat$group =="z"])  /10)*10 ,ceiling(max(dat$A_up[dat$group =="z"])/10)*10 )   
                      #limits =  c( floor(  min(dat$A_low[dat$group =="z"])  /10)*10 ,ceiling(max(dat$A_up[dat$group =="z"])/10)*10 ) 
                      limits =  c( floor(  min(dat$A_low)  /10)*10 ,ceiling(max(dat$A_up)/10)*10 ) 
                      ) +
    facet_wrap(~group ,ncol=2, scales = "free_y") 

i.e.

c( floor( min(dat$A_low) /10)*10 ,ceiling(max(dat$A_up)/10)*10 )

is 50 and 90

but I would like the limit to be unique to each facet plot so something like

so the right plot would have limits of

c( floor( min(dat$A_low[dat$group =="y"]) /10)*10 ,ceiling(max(dat$A_up[dat$group =="y"])/10)*10 )

50 and 70

and the left plot would have limit of

c( floor( min(dat$A_low[dat$group =="z"]) /10)*10 ,ceiling(max(dat$A_up[dat$group =="z"])/10)*10 )

70 and 90

how can the limits be adjusted to be specific to the individual facet plots?

like image 311
user3022875 Avatar asked Oct 19 '16 16:10

user3022875


People also ask

How do I change y axis limits in R?

To change the axis scales on a plot in base R Language, we can use the xlim() and ylim() functions. The xlim() and ylim() functions are convenience functions that set the limit of the x-axis and y-axis respectively.

What is the difference between Facet_wrap and Facet_grid?

While facet_grid shows the labels at the margins of the facet plot, facet_wrap creates a label for each plot panel.


2 Answers

dat = data.frame(x = c(1,2,3,1,2,3),A=c(80.6, 82,83,60,61,62),A_up =c(81,84,85,62,63,64), A_low =c(79,78,81,59,58,57), group = c("z","z","z","y","y","y"))


dat <- data.table(dat)

dat[, y_min := floor(  min(A_low)  /10)*10, by = group]
dat[, y_max := ceiling(max(A_up)/10)*10 , by = group]

ggplot(data=dat , aes(x=as.factor(x), y=A, group = 1)) + #, color =Group, group = Group 
  geom_line()  + geom_point() + # facet_wrap(~COUNTERPARTY_STRATEGY ,ncol=2)
  geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
  scale_y_continuous(breaks = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                    ceiling(  (max(dat$A_up)+11) /10)*10,10 ),
                     labels = seq(  floor(  (min(dat$A_low)-11)  /10)*10 ,
                                    ceiling(  (max(dat$A_up)+11) /10)*10,10 )
  ) +
  facet_wrap(~group ,ncol=2, scales = "free_y") + 
geom_blank(aes(y = y_min)) + geom_blank(aes(y = y_max))

So here I use data.table by = group to create y_min and y_max for each group. And then use those values in geom_blank to extend the plot area.

enter image description here

Obviously, this is automatically scalable to any number of groups/facets.

like image 167
Jav Avatar answered Nov 15 '22 20:11

Jav


One option is to make each of the facets separately, and then stitch them back together. This has the added benefit that you can use something other than 10 for your break sequencing (e.g., if one of your groups spans from 100 to 1000, you could use 200 instead with a little tinkering).

First, I am creating a function to calculate the breaks. (This is the function that you would modify if you want different scales for different ranges.)

myBreaks <- function(x){
  seq(floor( (min(x) )  /10)*10 ,
      ceiling( (max(x) ) /10)*10,
      10 )
}

Then, use lapply to make a plot from the subset of your data for each group:

sepPlots <- lapply(levels(dat$group), function(thisGroup){

  ggplot(data= dat[dat$group == thisGroup, ],
         aes(x=as.factor(x), y=A, group = 1)) +
    geom_line()  + geom_point() + 
    geom_errorbar(aes(ymax = A_up ,ymin = A_low), width = .25) +
    scale_y_continuous(breaks = myBreaks,
                       limits = range(myBreaks(dat[dat$group == thisGroup, c("A_up", "A_low")]))
                       ) +
    facet_wrap(~group)
})

Note that I still used facet_wrap in order to get the strip-style title above the plot, though you could just use ggtitle instead if you like that styling better.

Then, use plot_grid from cowplot to stitch everything back together. Do note that if you load cowplot it sets it's own default theme. To revert back, use theme_set(theme_gray())

cowplot::plot_grid(plotlist = sepPlots)

gives

enter image description here

cowplot is pretty well documented, so you should be able to make adjustments to the plot as needed when you scale up to more groups.

like image 37
Mark Peterson Avatar answered Nov 15 '22 20:11

Mark Peterson