Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reordering groups in Likert plots with R

Tags:

r

ggplot2

I'm using the jbryer/likert package to plot Likert data.

Consider the response table, called items—here, A, B, and so on are the column names, not part of the data:

A B C D
5 4 5 4
3 3 3 4
2 2 2 2
2 2 2 3
5 3 6 7
3 3 5 4

And the following code:

choices  = c("Very low", "Low", "Rather low", "Neither low nor high", "Rather high", "High", "Very high")
for(i in 1:ncol(items)) {
  items[,i] = factor(items[,i], levels=1:7, labels=choices, ordered=TRUE)
}

Now, we transform this into the likert data and plot it, which overrides the built-in plot function with one that uses ggplot:

plot(likert(items), ordered=FALSE)

This gives me:

Cool. All ordered. But A, B, etc. are not meaningful as descriptors for the conditions, and I'd like to override them:

names(items) = c("LT", "ST", "SemTag", "SemTagContext")

Which gives me the wrong order:

See how ST comes first, although it's the name for B? My ordering got changed to B, D, C, A.

How can I make it preserve the order and return the bars in D, C, B, A—or, with my new group names: SemTagContext, SemTag, ST, LT?

Note: The data table above is shortened. The bar widths in the plot don't reflect this short data example, but the full dataset I have. The problem is the same though.

like image 986
slhck Avatar asked Jan 19 '13 15:01

slhck


3 Answers

I decided to re-implement this myself, as jon suggested:

# additional requirements
library(ggplot2)
library(reshape2)
library(RColorBrewer)

# create summary table
table_summary = likert(items)

# reshape results
results = melt(table_summary$results, id.vars='Item')

# reorder results
results$Item = factor(results$Item, levels=c("LT", "ST", "SemTag", "SemTagContext"))

# some defaults
ymin = 0
text.size = 3

ggplot(results, aes(y=value, x=Item, group=Item)) + 
  geom_bar(stat='identity', aes(fill=variable)) + 
  ylim(c(-5,105)) + 
  coord_flip() +
  scale_fill_manual('Response', values=brewer.pal(7, "RdYlGn"), 
              breaks=levels(results$variable), 
              labels=levels(results$variable)) +
  geom_text(data=table_summary$summary, y=ymin, aes(x=Item, 
              label=paste(round(low), '%', sep='')), 
              size=text.size, hjust=1) +
  geom_text(data=table_summary$summary, y=100, aes(x=Item,
              label=paste(round(high), '%', sep='')), 
              size=text.size, hjust=-.2) +
  ylab('Percentage') + xlab('')

This produces the correct order:

like image 52
slhck Avatar answered Nov 13 '22 02:11

slhck


You can do this using the group.order parameter to specify the order. Use the names() function to obtain the names of the columns.

plot(likert_var, group.order=names(results)) 
like image 20
Joop Aué Avatar answered Nov 13 '22 03:11

Joop Aué


I added a pull request to Jason Bryer's package that adds fullname attributes to the columns, which are then used when you plot. Detailed writeup here http://reganmian.net/blog/2013/10/02/likert-graphs-in-r-embedding-metadata-for-easier-plotting/

Given that addition, you can do

db <- likert_add_fullnames(db, c(
  "X7"="Do you use sites like Facebook, Twitter, or GPlus?",
  "X8"="Do you participate in online communities organised around your interests? 
    (could be juggling, cooking, sports or academics, for example)?",
  "X10"="Do you know of online communities relevant to your discipline or the 
    courses you are taking now?"))
...

and then these names will be reflected when you plot.

like image 2
Stian Håklev Avatar answered Nov 13 '22 03:11

Stian Håklev