1

with a dataframe like below

set.seed(99)
data = data.frame(name=c("toyota", "nissan"), a=sample(1:10,2)/10,b=sample(-150:-50,2),c=sample(1e2:1e3,2),d=sample(1e3:1e5,2), e=sample(-15:30,2))

I'm trying to plot the various variables onto a single chart as below. This works well

library(ggplot2)
library(reshape2)
ggplot(melt(data, id = "name")) + 
  aes(name, value, fill = name) + 
  geom_col(position = "dodge") +
  facet_wrap(~ variable, scales = "free_y") +
  theme(
    axis.text.x=element_blank(),
    axis.text.y=element_blank()
    )

enter image description here

The issue I have is that I want the bars in each facet to be ordered with highest values first - how do I go about this ? Note that I still need to keep the order in legend as it is - that is nissan, toyota

user3206440
  • 4,749
  • 15
  • 75
  • 132

1 Answers1

4

I came up with the following idea after reading Mr. Flick's answer in this question. I would like to give him credit.

What Mr. Flick did in the question is to create a new factor variable. Right now you have Nissan and Toyota. But we want to assign a unique factor level for each of Nissan and Toyota; we want to create ten levels. We want to find the proper order for each of the car company in each level of variable. The outcome of this process is stored as foo. In the next step, we want to create a new factor variable, which is identical to foo in mutate() in the previous code. Then, assign levels using foo. In the code for ggplot, we want to use scales = "free".

library(reshape2)
library(dplyr)
library(ggplot2)

temp <- melt(data, id = "name")

# Deciding the level order

foo <- temp %>%
       group_by(variable) %>%
       mutate(foo = levels(reorder(factor(paste(name, variable, sep = ".")), -value))) %>%
       pull(foo)

# Creating a new factor variable and assign levels with foo.

out <- temp %>% 
       mutate(new = factor(interaction(name, variable), levels = foo))

ggplot(data = out, aes(x = new, y = value, fill = name)) +
geom_col(position = "dodge") +
facet_wrap(~ variable, scales = "free") +
labs(x = "", fill = "Car company") +
theme(axis.text.x = element_blank(),
      axis.text.y = element_blank()) 

enter image description here

jazzurro
  • 23,179
  • 35
  • 66
  • 76
  • tried this, I'm afraid it is not working as intended. In the graph above for variable `c` the bar corresponding to `toyota` should have come before `nissan` – user3206440 Jan 15 '18 at 05:30
  • @user3206440 Just apply `fct_rev(name)` within the `aes()` call. – Phil Jan 15 '18 at 05:35
  • 1
    @user3206440 Let me get back to you a bit later. I am at work now. – jazzurro Jan 15 '18 at 07:01
  • 1
    @user3206440 Thanks for waiting. I tried a few things and came up with the code above. This time, Nissan comes on left side for variable `b` and `c`. I think this is the right order. – jazzurro Jan 15 '18 at 14:36
  • @jazzurro - I tried this and it worked very well - thank you :). In case I want to show x-axis tick mark label text, how would I get rid of the `.variable` part from the label ? – user3206440 Jan 19 '18 at 15:24
  • @user3206440 you mean something like `.a` in the x-axis text? If that is the case, you perhaps want to use `gsub()` as Mr. Flick did in the question that I cited. – jazzurro Jan 19 '18 at 16:38
  • 1
    @user3206440 I had a chance to sit down and think about the x label issue. I initially thought `scale_x_discrete(breaks = new, labels = gsub(pattern = "(^.*)\\..*$", replacement = "\\1", x = new))` would do the job. But this is causing an error. I am still thinking what is causing this. – jazzurro Jan 20 '18 at 12:27
  • @user3206440 I just saw you posted a new question and I came back to this challenge again. The following code is working with the sample data here. Somehow we need to specify `out$new` rather than `new`. Give it a go. `ggplot(data = out, aes(x = new, y = value, fill = name)) + geom_col(position = "dodge") + facet_wrap(~ variable, scales = "free") +labs(x = "", fill = "Car company") + theme(axis.text.y = element_blank()) +scale_x_discrete(breaks = out$new, labels = gsub(pattern = "(^.*)\\..*$", replacement = "\\1", x = out$new)) ` – jazzurro Jan 22 '18 at 13:08