user3196167
user3196167

Reputation: 57

ggplot2 in R: some variables have multiple groupings

I'm trying to plot odds ratios, but running into an issue because some of my variables have more than one group. As an example, CatA and CatC have one group ("S1"), but CatB and CatD have two groups ("S1" and "S2").

dfex = data.frame(stringsAsFactors=FALSE,
                  Category = c("CatA", "CatB", "CatB", "CatC", "CatD", "CatD"),
                  Grouping = c("S1", "S1", "S2", "S1", "S1", "S1"),
                  Odds = c(2.4, 3, 2.6, 2.4, 2.4, 1.7),
                  CILow = c(1.3, 1.2, 1.1, 1.2, 1.1, 0.8),
                  CIHigh = c(4.5, 4.6, 7.9, 5, 5.9, 3.7)
)

ggplot(dfex, aes(x = Odds, y = Category)) +
  geom_vline(aes(xintercept = 1), size = .25, linetype = 'dashed') +
  geom_errorbarh(aes(xmax = CIHigh, xmin = CILow), size = .5, height = 
                   .2, color = 'gray50') +
  geom_point(size = 3.5) +
  theme(panel.grid.minor = element_blank()) +
  scale_x_continuous(breaks = seq(0,7,1) ) +
  coord_trans(x = 'log10') +
  ylab('') +
  xlab('Odds ratio')

odds ratio with overlapping groups for some variables

I'm looking for a way to including the Grouping variable so that the name ("S1" or "S2") appears and also that the different groups in CatB and CatD be slightly offset so you could see both.

Less important, is there a simple way to have CatA at the top, to match the order of the data frame, without setting a new order for the factor?

Upvotes: 1

Views: 398

Answers (1)

dc37
dc37

Reputation: 16178

A possible way of doing is to "facet" your plot:

ggplot(dfex, aes(x = Odds, y = Grouping))+
  geom_errorbarh(aes(xmax = CIHigh, xmin = CILow), size = .5, height = 
                   .2, color = 'gray50') +
  geom_point(size = 3.5) +
  theme(panel.grid.minor = element_blank()) +
  scale_x_continuous(breaks = seq(0,7,1) ) +
  coord_trans(x = 'log10') +
  ylab('') +
  xlab('Odds ratio')+
  facet_grid(Category~., switch = "y", scales = "free_y")+
  theme(strip.placement = "outside",
        strip.text.y = element_text(angle = 180),
        strip.background.y = element_blank(),
        panel.spacing = unit(-1, "lines"))

enter image description here

An alternative solution is to use interaction to group your y values with both Category and Grouping.

You can also pass reorder function in each of them if you don't want to reorder factors before the use of ggplot:

ggplot(dfex, aes(x = Odds, 
                 y = interaction( reorder(Category, desc(Category)), reorder(Grouping,desc(Grouping)))))+
  geom_vline(aes(xintercept = 1), size = .25, linetype = 'dashed') +
  geom_errorbarh(aes(xmax = CIHigh, xmin = CILow), size = .5, height = 
                          .2, color = 'gray50') +
  geom_point(size = 3.5) +
  theme(panel.grid.minor = element_blank()) +
  scale_x_continuous(breaks = seq(0,7,1) ) +
  coord_trans(x = 'log10') +
  ylab('') +
  xlab('Odds ratio')

enter image description here

Does it answer your question ?


Update with ggplot2 v3.3.0

Minor tweaks to get the first solution working ggplot2 v3.3.0 is to replace:

strip.text.y = element_text(angle = 180),

with

strip.text.y.left = element_text(angle = 0),

Upvotes: 1

Related Questions