Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
252 views
in Technique[技术] by (71.8m points)

r - add multi x-axis ggplot2 or customized labels to stack bar plot

Hei,

I am trying to add informations of the depth range integrated (1) on the x-axis or (2) on the top of stack bars of the graph (or something similar). See the pictures below.

enter image description here

with the labels: enter image description here

(1) not sure how to do it.

(2) To plot the infos on top of stacked bar I have first create the variable:

depth_int <- c("5-200 m", "5-181 m", "5-200 m", "5-200 m", "5-155 m", "5-200 m", "5-200 m", 
             "5-90 m", "10-60 m", "10-90 m", "10-30 m", "20-90 m", "0.5-30 m", "0.5-90 m", "0.5-90 m")

and by using this function on my ggplot(): geom_text(aes(label = depth_int), hjust = 0, position = "stack")

I get this error: Error: Aesthetics must be either length 1 or the same as the data (164): label

(I guess its because the stacked bar is a combination of the taxa and then you cannot plot only 1 value on the top of the bar per stations (e.g., P1).

-

this is my script:

ggplot(df, aes(x=locationID, fill=class, y = V1))+
  geom_bar(stat="identity", position = "stack", width = 0.9)+
  facet_grid(. ~ expedition, scales="free_x") +
  #scale_fill_manual(values = default_colors, labels= c("","",""))          #default_colors<-c("#F8766D", "#00BA38", "#619CFF")
  # change the label names in the legend
  labs(title = "Taxa abundance per depth integrated", fill = "Taxa", 
       x= bquote('Stations'),
       y= bquote('Abundance'~(cells~m^-3)))+ 
  theme_minimal()+
    theme(panel.grid.major.y = element_line(size = 0.5, linetype = 'solid',
                                          colour = "grey75"),
          panel.grid.minor.y = element_line(size = 0.5, linetype = 'solid',
                                            colour = "grey75"),
          panel.grid.major.x = element_blank(),
        panel.background = element_rect(fill = "white", colour = "grey75"),
        axis.text.x = element_text(colour="black",size=7),
        axis.text.y = element_text(colour="black",size=10),
        axis.title.x = element_text(colour="black",size=10),
        axis.title.y = element_text(colour="black",size=10),
        plot.title = element_text(colour = "black", size = 10, face = "bold"),
        legend.position = "right",
        legend.text = element_text(size=10),
        legend.title = element_text(size = 11, hjust =0.5,  vjust = 3, face = "bold"),
        legend.key.size = unit(10,"point"),
        legend.spacing.y = unit(-.25,"cm"),
        legend.margin=margin(0,5,8,5), 
        legend.box.margin=margin(-10,10,-3,10),
        legend.box.spacing = unit(0.5,"cm"),
        plot.margin = margin(2,2,0,0)) 
question from:https://stackoverflow.com/questions/65888871/add-multi-x-axis-ggplot2-or-customized-labels-to-stack-bar-plot

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Simply passing a vector labels to geom_text will not work. To achieve your desired result you could

  1. Summarise your data to get the total height of the bars by location and expedition

  2. Add your labels to the summarised dataframe. To this end I use a dataframe of labels by location and expedition which I join to the summarised df.

  3. Use the summarised dataframe as data in geom_text

Note: As the summarised df has no column class I have put fill=class as a local aes inside geom_bar.

Using some random example data try this:

library(ggplot2)
library(tidyr)
library(dplyr)

# Random example dataset
set.seed(42)
df <- data.frame(
  locationID = c(sample(LETTERS[1:4], 50, replace = TRUE), sample(LETTERS[5:8], 50, replace = TRUE)),
  class = sample(letters[1:4], 100, replace = TRUE),
  expedition = rep(paste("expedition", 1:2), each = 50),
  V1 = runif(100)
)

# Make a dataframe of labels by expedition and locationID
depth_int <- tidyr::expand(df, nesting(expedition, locationID))
depth_int$label <- c("5-200 m", "5-181 m", "5-200 m", "5-200 m", "5-90 m", "10-60 m", "10-90 m", "10-30 m")
depth_int
#> # A tibble: 8 x 3
#>   expedition   locationID label  
#>   <chr>        <chr>      <chr>  
#> 1 expedition 1 A          5-200 m
#> 2 expedition 1 B          5-181 m
#> 3 expedition 1 C          5-200 m
#> 4 expedition 1 D          5-200 m
#> 5 expedition 2 E          5-90 m 
#> 6 expedition 2 F          10-60 m
#> 7 expedition 2 G          10-90 m
#> 8 expedition 2 H          10-30 m

# Summarise your data to get the height of the stacked bar and join the labels
df_labels <- df %>% 
  group_by(locationID, expedition) %>% 
  summarise(V1 = sum(V1)) %>% 
  left_join(depth_int, by = c("locationID", "expedition"))

ggplot(df, aes(x=locationID, y = V1))+
  geom_bar(aes(fill=class), stat="identity", position = "stack", width = 0.9) +
  # Use summarised data to put the labels on top of the stacked bars
  geom_text(data = df_labels, aes(label = label), vjust = 0, nudge_y = 1) +
  facet_grid(. ~ expedition, scales="free_x") +
  labs(title = "Taxa abundance per depth integrated", 
       fill = "Taxa", 
       x= bquote('Stations'),
       y= bquote('Abundance'~(cells~m^-3)))+ 
  theme_minimal()+
  theme(panel.grid.major.y = element_line(size = 0.5, linetype = 'solid',
                                          colour = "grey75"),
        panel.grid.minor.y = element_line(size = 0.5, linetype = 'solid',
                                          colour = "grey75"),
        panel.grid.major.x = element_blank(),
        panel.background = element_rect(fill = "white", colour = "grey75"),
        axis.text.x = element_text(colour="black",size=7),
        axis.text.y = element_text(colour="black",size=10),
        axis.title.x = element_text(colour="black",size=10),
        axis.title.y = element_text(colour="black",size=10),
        plot.title = element_text(colour = "black", size = 10, face = "bold"),
        legend.position = "right",
        legend.text = element_text(size=10),
        legend.title = element_text(size = 11, hjust =0.5,  vjust = 3, face = "bold"),
        legend.key.size = unit(10,"point"),
        legend.spacing.y = unit(-.25,"cm"),
        legend.margin=margin(0,5,8,5), 
        legend.box.margin=margin(-10,10,-3,10),
        legend.box.spacing = unit(0.5,"cm"),
        plot.margin = margin(2,2,0,0)) 


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...