vasdam
vasdam

Reputation: 15

Plot a barplot with repeated labels

I would like to plot data with repeated x-axis labels in the form of bar-plot without merging the values with repeated labels.

In the example I have a table de:

Table with data

de <- data.frame(mean=c(10, 2, 3, 1, 4, 5, 3, 9),
                 base=c('A','A','C','G','T','T','T','A'))

And I would like to have a plot like this:

correct plot

But when I run this in R:

ggplot(de, aes( y = mean, x =base))+
    geom_bar(stat = 'identity')

This is what I get:

wrong plot

It merges the identical bases into one column, whereas I want a separate column for each value of base, even the repeated ones, as shown in the table above.

Upvotes: 1

Views: 1633

Answers (3)

divibisan
divibisan

Reputation: 12155

Building off @sargg's excellent answer, we can prevent the possibility of human error by generating the unique base names and the ggplot labels automatically with dplyr:

library(dplyr)
de2 <- de %>%
    group_by(base) %>%
    mutate(unique_base = paste0(base, row_number()))

# A tibble: 8 x 3
# Groups:   base [4]
   mean base  unique_base
  <dbl> <fct> <chr>      
1    10 A     A1         
2     2 A     A2         
3     3 C     C1         
4     1 G     G1         
5     4 T     T1         
6     5 T     T2         
7     3 T     T3         
8     9 A     A3 

ggplot(de2, aes(y = mean, x =unique_base))+ 
    geom_bar(stat = 'identity') + 
    scale_x_discrete(labels=de2$base)

enter image description here

For an even DRY-er answer, we can pass the data in like this (note the curly braces: see this answer for more information):

de2 %>% {
    ggplot(., aes( y = mean, x =unique_base))+ 
        geom_bar(stat = 'identity') + 
        scale_x_discrete(labels=.$base)
}

This lets us access the de2 data frame from within the ggplot call with ., thus letting us specify the labels with labels=.$base, rather than having to specify the dataframe de2 twice.

Upvotes: 1

Rui Barradas
Rui Barradas

Reputation: 76402

Though there already is an accepted solution, I will post another one, creating the desired labels from the original dataset.

First, an example dataset creation code.

set.seed(1234)
values <- sample(20, 8)
base <- c('A', 'A', 'C', 'G', 'T', 'T', 'T', 'A')
de <- data.frame(base, values)

Now the code to plot the graph.

library(tidyverse)

de %>%
  mutate(base1 = paste0(seq_along(base), base)) %>%
  ggplot(aes(x = base1, y = values)) +
  geom_bar(stat = 'identity') +
  geom_text(aes(x = base1, y = -1,
                 label = base)) +
  theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

enter image description here

Upvotes: 0

sargg
sargg

Reputation: 333

The easy way is to:

  • Set non-unique labels for As and Ts in your "base" column; for example Ax, Ay, Tx, Ty etc:
de <- data.frame(mean=c(10, 2, 3, 1, 4, 5, 3, 9), 
  base=c("Ax", "Ay", "C", "G", "Tx","Ty", "Tz", "A"))

And then change the x-axis labels:

ggplot(de, aes( y = mean, x =base))+ 
  geom_bar(stat = 'identity') + 
  scale_x_discrete(labels=c("A", "A", "C", "G", "T","T", "T", "A"))

Upvotes: 1

Related Questions