1

I am pretty new to R and i'm trying to get a stacked bar plot. My data looks like this:

    name    value1  value2
1   A       1118    239
2   B       647     31
3   C       316     1275
4   D       2064    230
5   E       231     85

I need a horizontal bar graph with stacked values, this is as far as i can get with my limited R skills (and most of that is also copy-pasted):

melted <- melt(data, id.vars=c("name"))

melted$name <- factor(
  melted$name, 
  levels=rev(sort(unique(melted$name))), 
  ordered=TRUE
)

melted2 <- melted[order(melted$value),]

ggplot(melted2, aes(x= name, y = value, fill = variable)) + 
  geom_bar(stat = "identity") +
  coord_flip()

It even took me several hours to get to this point, with witch I am pretty content as far as looks go, this is the produced output

enter image description here

What I now want to do is to get the bars ordered by summed up value (D is first, followed by C, A, B, E). I googled and tried some reorder and order stuff, but I simply can't get it to behave like I want it to. I'm sure the solution has to be pretty simple, so I hope you guys can help me with this.

Thanks in advance!

rawr
  • 20,481
  • 4
  • 44
  • 78
Mihael
  • 13
  • 3
  • http://stackoverflow.com/questions/5208679/order-bars-in-ggplot2-bar-graph – rawr Mar 07 '15 at 14:05
  • I already saw that page, but can't seem to be able to work it into my own code... Can you give me a hint how to implement into my routine? Sorry that I'm such a noob. – Mihael Mar 07 '15 at 14:19

3 Answers3

1

Well, I am not down or keeping up with all the latest changes in ggplot, but here is one way you could remedy this

I used your idea to set up the factor levels of name but based on the grouped sums. You might also find order = variable useful at some point, which will order the bar colors based on the variable, but not needed here

data <- read.table(header = TRUE, text = "name    value1  value2
1   A       1118    239
2   B       647     31
3   C       316     1275
4   D       2064    230
5   E       231     85")

library('reshape2')
library('ggplot2')

melted <- melt(data, id.vars=c("name"))

melted <- within(melted, {
  name <- factor(name, levels = names(sort(tapply(value, name, sum))))
})

levels(melted$name)
# [1] "E" "B" "A" "C" "D"

ggplot(melted, aes(x= name, y = value, fill = variable, order = variable)) + 
  geom_bar(stat = "identity") +
  coord_flip()

enter image description here

rawr
  • 20,481
  • 4
  • 44
  • 78
1

Another option would be to use the dplyr package to set up a total column in your data frame and use that to sort. The approach would look something like this.

m <- melted %>% group_by(name) %>% 
     mutate(total = sum(value) ) %>% 
     ungroup() %>%
     arrange(total) %>%
     mutate(name = factor(name, levels = unique(as.character(name))) )

ggplot(m, aes(x = name, y = value, fill = variable)) + geom_bar(stat = 'identity') + coord_flip()
jraab
  • 413
  • 4
  • 10
1

Note that trying below code.

  • using tidyr package instead to reshape2 package

    library(ggplot2)
    library(dplyr)
    library(tidyr)
    
    data <- read.table(text = "
                       class value1 value2
                       A     1118   239
                       B     647    31
                       C     316    1275
                       D     2064   230
                       E     231    85", header = TRUE)
    
        pd <- gather(data, key, value, -class) %>% 
          mutate(class = factor(class, levels = tapply(value, class, sum) %>% sort %>% names))
    
        pd %>% ggplot(aes(x = class, y = value, fill = key, order = class)) + 
          geom_bar(stat = "identity") +
      coord_flip()
    
Lovetoken
  • 438
  • 4
  • 11