2

I intend to plot every categorical column in the dataframe in a descending order depends on the frequency of levels in a variable.

I have already found out how to plot every column and reorder the levels, but I cannot figure out how to combine them together. Could you please give me some suggestions?

Code for plot every column:

require(purrr)
library(tidyr)
library(ggplot2)


diamonds %>% 
  keep(is.factor) %>%
  gather() %>%
  ggplot(aes(value)) +
  facet_wrap(~ key, scales = "free") +
  geom_bar()  

Code for reorder the levels of one variable:

tb <- table(x)
factor(x, levels = names(tb[order(tb, decreasing = TRUE)]))

BTW, if you feel there is a better way writing these codes, please let me know. Thanks.

Evan Liu
  • 37
  • 1
  • 5
  • Can you please add a reproducible data (bank_add in this case) for your question? – Adam Quek Apr 12 '17 at 03:41
  • (1) you have one too many `r`s in your code. (2) What is `bank_add`? (And please don't respond with just "it's my data", since that doesn't help me understand anything, including number 3 here.) (3) What does "descending order" mean when talking about whole columns of data? Is it descending `sum`s, `min`s, `max`s, `mean`s, `cor`s, `t.test`s, or something else? (If you make this question a little more [reproducible](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example), we might be able to give you more salient help.) – r2evans Apr 12 '17 at 03:41
  • Thanks for your advice. I made some changes. Now I am using diamonds data from ggplot2 package. Also "descending order" means the frequency of levels in a categorical variables. – Evan Liu Apr 12 '17 at 04:20

2 Answers2

3

Alternative 1

No need to use gridExtra to emulate facet_wrap, just include the function reorder_size inside aes:

reorder_size <- function(x) {
  factor(x, levels = names(sort(table(x), decreasing = TRUE)))
}

diamonds %>% 
  keep(is.factor) %>%
  gather() %>%
  ggplot(aes(x = reorder_size(value))) +
  facet_wrap(~ key, scales = "free") +
  geom_bar()  

Alternative 2

Using dplyrto calculate the count grouping by key and value. Then we reorder the value in descending order by count inside aes.

library(dplyr)
diamonds %>% 
  keep(is.factor) %>%
  gather() %>%
  group_by(key,value) %>% 
  summarise(n = n()) %>% 
  ggplot(aes(x = reorder(value, -n), y = n)) +
  facet_wrap(~ key, scales = "free") +
  geom_bar(stat='identity') 

Output enter image description here

mpalanco
  • 12,960
  • 2
  • 59
  • 67
1

The problem with your approach is that the long form of your data-frame will introduce a lot of factors that would be plotted as 0 for the geom_bar().

Instead of relying on facet_wrap and dealing with the long data-form, here's an alternative.

Reordering by size function:

reorder_size <- function(x) {
  factor(x, levels = names(sort(table(x), decreasing=T)))
}

Using gridExtra::grid.arrange function to deliver similar facet_wrap style figure:

library(gridExtra)
a <- ggplot(diamonds, aes(x=reorder_size(cut))) + geom_bar()
b <- ggplot(diamonds, aes(x=reorder_size(color))) + geom_bar()
c <- ggplot(diamonds, aes(x=reorder_size(clarity))) + geom_bar()
grid.arrange(a,b,c, nrow=1)

enter image description here

Adam Quek
  • 6,973
  • 1
  • 17
  • 23