1

I was trying to make bars in clustered column plot appearing with a decreasing ordered based on values of y axis(pososto).I tryed aes(x=reorder(allele,-pososto,sum(and mean)) but those didn't work.If someone can help it would be perfect. Thank you in advance!

Part of my data:

df <- structure(list(allele = c("Ak24:02", "Ak24:02", "Ak24:02", "Ak24:02", 
"Ak02:01", "Ak02:01", "Ak02:01", "Ak02:01", "Ak01:01", "Ak01:01", 
"Ak01:01", "Ak01:01", "Ak11:01", "Ak11:01", "Ak11:01", "Ak11:01", 
"Ak03:01", "Ak03:01", "Ak03:01", "Ak03:01", "Ak32:01", "Ak32:01", 
"Ak32:01", "Ak32:01", "Ak26:01", "Ak26:01"), subject = c("her", 
"reth", "las", "xan", "her", "reth", "las", "xan", "her", "reth", 
"las", "xan", "her", "reth", "las", "xan", "her", "reth", "las", 
"xan", "her", "reth", "las", "xan", "her", "reth"), pososto = c(6.2076749, 
0, 14.3529412, 0, -0.7751938, 0, -0.7751938, 0, 5.0666604, 0, 
0, 11.944798, 0, 0, 9.7559913, 6.0631187, -12.4022258, -1.3476446, 
13.1983584, 17.1626014, 0, -13.1511297, 14.7583726, -5.6592186, 
0, 0)), class = "data.frame", row.names = c("1", "2", "3", "4", 
"5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", 
"16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
))

My basic code:

    df = data.frame(allele, subject, pososto)
  df$subject <- factor(df$subject, levels =c("her", "xan", "las", "reth"))
  df$pososto = as.numeric(df$pososto)
  p=ggplot(df, aes(x = allele, y = pososto, fill = subject)) + 
    geom_bar(position = "dodge",stat = "identity", aes(fill= subject)) +
    #gia labels
    # geom_text(aes(label = round(count, 2)),position = position_dodge(width = 0.9),
    #             vjust = ifelse(df[,3]>=0, -0.5, 1) , size= 3)+
    scale_x_discrete(limits = (unique(df$allele))) +
    scale_fill_manual(values=c("#696969","#778899","#A9A9A9","#CCCCFF"))+
    theme_bw(base_size = 9) +
    geom_hline(yintercept = 0, colour = "black") +
    theme(axis.text.x = element_text(angle = 60, hjust = 1))strong text`

dataframe is looking like this:

enter image description here

The plot I am taking from basic code:

enter image description here

TarJae
  • 72,363
  • 6
  • 19
  • 66
Mel
  • 45
  • 5
  • To help us to help would you mind sharing [a minimal reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) including a snippet of your data or some fake data. – stefan Jan 16 '22 at 12:55
  • 1
    Oh,I am sorry I forgot to upload them.I will edit my quest.Thanks! – Mel Jan 16 '22 at 13:04
  • (: Please do not post an image of code/data/errors [for these reasons](https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-errors-when-asking-a-question/285557#285557) (and xkcd.com/2116). To share your data, you could type `dput(NAME_OF_DATASET)` into the console and paste the output starting with `structure(....` into your post. If your dataset has a lot of observations you could do e.g. `dput(NAME_OF_DATASET[1:20, ])` for the first twenty rows of data. – stefan Jan 16 '22 at 13:12
  • ... this said: The question is how you will reorder your bars? As there are multiple bars with negative and positive values `reorder(..., sum)`will e.g. reorder by the sum over all bars per `allele`. – stefan Jan 16 '22 at 13:14
  • Thank you.Is there any way that can make all bars shown in descending order regardless of each allele? – Mel Jan 16 '22 at 13:21

2 Answers2

2

Maybe this is what you are looking for. To order the bars in decreasing order without grouping by allele you could add a helper variable via interaction which could then be mapped on x.

To only show the allele on the x axis I make use of a custom labels function in scale_x_discrete and use an underscore as separator in interaction.

library(ggplot2)

df$subject <- factor(df$subject, levels =c("her", "xan", "las", "reth"))
df$pososto = as.numeric(df$pososto)

df$x <- interaction(df$allele, df$subject, sep = "_")

ggplot(df, aes(x = reorder(x, -pososto), y = pososto, fill = subject)) + 
  geom_col(position = "dodge") +
  scale_x_discrete(labels = ~ gsub("^(.*?)_.*$", "\\1", .x)) +
  scale_fill_manual(values=c("#696969","#778899","#A9A9A9","#CCCCFF"))+
  theme_bw(base_size = 9) +
  geom_hline(yintercept = 0, colour = "black") +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Yes,It seems what I need.! I tried it but nothing has changed..I don't know if I am doing something wrong.. ... df$subject <- factor(df$subject, levels =c("her", "xan", "las", "reth")) df$pososto = as.numeric(df$pososto) df$x <- interaction(df$allele, df$subject, sep = "_") p=ggplot(df, aes(x=reorder(allele,-pososto), y = pososto, fill = subject)) + geom_bar(position = "dodge",stat = "identity", aes(fill= subject)) + scale_x_discrete(labels = ~ gsub("^(.*?)_.*$", "\\1", .x)) +... – Mel Jan 16 '22 at 13:44
  • @stefan, this looks sound. Though, I am still wondering how one could sort descending `pososto` within each `allelle`. So, basically, having 7 distinct levels if `allelle` ∈ {Ak24, Ak11, ..., Ak32} and sort descending based on `pososto` within each level. – Dion Groothof Jan 16 '22 at 14:51
  • 1
    Hi @Mel. The issue is that you did `aes(x=reorder(allele,-pososto), ...` instead of mapping the helper variable x on the x aes, i.e. do `aes(x=reorder(x,-pososto), ...`. – stefan Jan 16 '22 at 16:59
  • 1
    Thank you so much!I tryied to order the dataframe based on pososto column with abs values and it worked.I'm gonna try your way too. (I did: df=df[order(abs(as.numeric(df$pososto)),decreasing = TRUE),] after I created the dataframe,if someone needs this) – Mel Jan 16 '22 at 17:02
  • @Dion. Have a look at the answer by TarJae. There are as always different ways to achieve this result. But the most simple in my opinion is indeed to rearrange the dataset and then fixing the order, where I probably would have made use of `forecast::fct_inorder` but TarJae's approach using `row_number` is also absolutely fine. – stefan Jan 16 '22 at 17:02
  • 1
    @stefan Thanks for notifying me and you're right. – Dion Groothof Jan 16 '22 at 17:08
2

Are you looking for such a solution?

library(tidyverse)
df %>% 
  arrange(allele, pososto, subject) %>% 
  group_by(allele) %>% 
  mutate(id=row_number()) %>%
  mutate(subject = fct_reorder(allele, id)) %>%
  ggplot(aes(x = allele, y = pososto, fill=factor(id))) + 
  geom_col(position=position_dodge())+
  scale_x_discrete(limits = (unique(df$allele))) +
  theme_bw(base_size = 9) +
  geom_hline(yintercept = 0, colour = "black") +
  scale_fill_manual(values=c("#696969","#778899","#A9A9A9","#CCCCFF"), labels = c("her", "reth", "las", "xan"))+
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

data:

df <- structure(list(allele = c("Ak24:02", "Ak24:02", "Ak24:02", "Ak24:02", 
"Ak02:01", "Ak02:01", "Ak02:01", "Ak02:01", "Ak01:01", "Ak01:01", 
"Ak01:01", "Ak01:01", "Ak11:01", "Ak11:01", "Ak11:01", "Ak11:01", 
"Ak03:01", "Ak03:01", "Ak03:01", "Ak03:01", "Ak32:01", "Ak32:01", 
"Ak32:01", "Ak32:01"), subject = c("her", "reth", "las", "xan", 
"her", "reth", "las", "xan", "her", "reth", "las", "xan", "her", 
"reth", "las", "xan", "her", "reth", "las", "xan", "her", "reth", 
"las", "xan"), pososto = c(6.2076749, 0, 14.3529412, 0, -0.7751938, 
0, -0.7751938, 0, 5.0666604, 0, 0, 11.944798, 0, 0, 9.7559913, 
6.0631187, -12.4022258, -1.3476446, 13.1983584, 17.1626014, 0, 
-13.1511297, 14.7583726, -5.6592186)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"
))

enter image description here

TarJae
  • 72,363
  • 6
  • 19
  • 66