Home > Blockchain >  Create x axis labels for dodged subgroup in barplot
Create x axis labels for dodged subgroup in barplot

Time:12-31

I am trying to have this barplot use the data from column SPP as the x axis labels rather than funct_form, but unsure how to do this.

data sample:

top32reads <- structure(list(identifier = 1:10, SPP = c("Penstemon", "Rosaceae Group 1", 
"Abies", "Hypericum", "Saxifraga OR Micranthes OR Boykinia", 
"Eriogonum", "Vaccinium", "Oenothera", "Oxyria digyna", "Chamerion"
), max = c(0.520063568, 0.479127183, 0.503981446, 0.717687654, 
0.434079314, 0.362801825, 0.191388889, 0.219305556, 0.263381525, 
0.383032052), readsum = c(6.716942576, 5.503499137, 3.881683753, 
3.798417906, 3.49976764, 2.309000619, 1.913782497, 1.616440058, 
1.59921115, 1.478810665), funct_type = c("Forb", "Forb", "Conifer", 
"Forb", "Forb", "Forb", "Shrub", "Forb", "Forb", "Forb"), frequencyformula = c(52L, 
50L, 40L, 45L, 47L, 47L, 46L, 43L, 40L, 41L), frequency = c(1, 
0.961538462, 0.769230769, 0.865384615, 0.903846154, 0.903846154, 
0.884615385, 0.826923077, 0.769230769, 0.788461538)), row.names = c(NA, 
10L), class = "data.frame")

barplot code:

library(ggplot2)
library(dplyr)
library(forcats)
library(scales)
library(colorspace)

top32reads%>%
  mutate(funct_type = fct_reorder(.f = funct_type, .x = -readsum, min),
         main_color = brewer_pal("qual")(n_distinct(funct_type))[funct_type]
  ) %>%
  group_by(funct_type) %>% 
  mutate(lvl = as.integer(fct_reorder(SPP, readsum)),
         relvl = rescale(lvl, c(0, .6), from = c(0, max(length(lvl), 5))),
         sub_color = darken(main_color, relvl)) %>% 
  ggplot(aes(x = funct_type, y = readsum))   
  geom_col(aes(fill = sub_color),
           position = position_dodge2(width = .9, preserve = "single"))  
  scale_fill_identity()  
  ylab("Sum of read percentages across samples")  
  xlab("OTUs Consumed by Functional Type")  
  ggtitle("Diet by Relative Read Abundance")  
  theme_bw()  
  theme(axis.title = element_text(size = 16, face = "bold"),
        strip.text.y = element_text(size = 18, face="bold"),
        plot.title = element_text(size = 28, face = "bold", hjust = 0.5),
        axis.text = element_text(size = 18, face = "bold"),
        legend.position = "bottom")

enter image description here

when i try to switch out SPP for funct_type in aes(), (also adding axis.text.x=element_text(angle=90)) I end up with this enter image description here

which obviously does not have the same ordering and spacing as previously

CodePudding user response:

Revised Answer

If you want to keep everything the same but use SPP for the x-axis you just need to update the ggplot call. e.g.

ggplot(aes(x = SPP, y = readsum))

And you can use coord_flip to rotate the axes.

Which gets you this.

enter image description here

Old Answer

Is this what you're thinking? I removed some of the extra styling you had for demonstrative purposes. Also it's helpful in the future to include all the packages that you're using for the reprex.

You can use facet_wrap to display different groups which in this case are shown at the top. Then use SPP as your x variable.

library(ggplot2)
library(dplyr)
library(forcats)
library(scales)
library(colorspace)

top32reads = top32reads %>%
  mutate(funct_type = fct_reorder(.f = funct_type, .x = -readsum, min),
         main_color = brewer_pal("qual")(n_distinct(funct_type))[funct_type]
  ) %>%
  group_by(funct_type) %>% 
  mutate(lvl = as.integer(fct_reorder(SPP, readsum)),
         relvl = rescale(lvl, c(0, .6), from = c(0, max(length(lvl), 5))),
         sub_color = darken(main_color, relvl)) %>%
  ungroup()

top32reads %>%
  ggplot(aes(x = SPP, y = readsum))   
  geom_col(aes(fill = sub_color),
           position = position_dodge2(width = .9, preserve = "single"))  
  scale_fill_identity()  
  ylab("Sum of read percentages across samples")  
  xlab("OTUs Consumed by Functional Type")  
  ggtitle("Diet by Relative Read Abundance")  
  theme_bw()  
  facet_wrap(~ funct_type)   
  coord_flip()

enter image description here

CodePudding user response:

This is actually not trivial. I think user Jamie's idea of using facets is very good 1. But it requires a bit more work on the underlying ordered factors. You have already created an ordered factor by function type (well done), but then you did not make use of it as your x variable. Do it!

You will see, I have retained the function type labels (as strips in the facets. You can also completely remove them, (using theme), and if you want more space between your funcion types, increase the strip spacing with panel.spacing. I've removed a lot of unnecessary code for the problem. Some comments in the code.

## when doing complex data wrangling, 
## I prefer to first create a proper object 
## instead of piping into ggplot directly
df_fct <-
top32reads %>%
  mutate(funct_type = fct_reorder(.f = funct_type, .x = -readsum, min),
         main_color = brewer_pal("qual")(n_distinct(funct_type))[funct_type]
  ) %>%
  group_by(funct_type) %>% 
  ## don't convert your factor to integer yet
  mutate(lvl = fct_reorder(SPP, desc(readsum)),
  ## but only now
         relvl = rescale(as.integer(lvl), c(0, .6), from = c(0, max(length(lvl), 5))),
         sub_color = darken(main_color, relvl), 
  ## this is just one suggestion to reformat the labels. 
  ## There are other ways to deal with the long labels 
  ## e.g., user jamie has flipped the coordinates which I find a good idea
  spp_lab = factor(lvl, levels = levels(lvl), labels = gsub(" ", "\n", levels(lvl)))) 
  
ggplot(df_fct , aes(x = spp_lab , y = readsum))   
  geom_col(aes(fill = sub_color),
           position = position_dodge2(width = .9, preserve = "single"))  
  scale_fill_identity()  
  ## facet by funct_type, switch strip to bottom
  facet_grid(~funct_type, switch = "x", scales = "free_x", space = "free_x")  
  ## place strip outside
  theme(strip.placement = "outside")

enter image description here

  • Related