Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering bars in barplot()

Tags:

graph

r

I have a dataframe, and one of the variables (let's call it Q1) has several levels: "No use", "30 min", "1 hour", "2 hours", "3+ hours".

How can I plot a barplot(), where the bars are in the order of factor levels? I tried using sort(), but that doesn't do the trick.

EDIT: As requested, some sample data:

Q1
1 hour
1 hour
30 min
2 hours
3+ hours
3+ hours
3+ hours
3+ hours
2 hours
1 hour
2 hours
1 hour
30 min

I've tried:

barplot(table(sort(Q1)), main = "Q1 Answer Distribution", ylim = c(0, 250), cex.axis=0.9)

but it doesn't give me what I need.

like image 730
neuron Avatar asked Mar 22 '26 21:03

neuron


2 Answers

One possibility is to create a factor version of Q1 where you specify the levels in the desired order:

df$Q1_fac <- factor(df$Q1, levels = c("30 min", "1 hour",  "2 hours", "3+ hours"))

tt <- table(df$Q1_fac)
tt
# Q1_fac
# 30 min   1 hour  2 hours 3+ hours 
#      2        4        3        4    

barplot(tt)

enter image description here

like image 107
Henrik Avatar answered Mar 25 '26 13:03

Henrik


As stated by Henrik, you need to get your data into a factor (at least this is the easiest easiest way to make this happen). Consider the following example with some fake data...

#generate 1000 random uniform integers between 1 and 5
data <- floor(runif(1000, 1,6)) 

#make data a factor with given labels
fdata <- factor(data,
                labels = c("No use", 
                           "30 min", 
                           "1 hour", 
                           "2 hours", 
                           "3+ hours"))

This can be done in base r with plot (barplot is not required when y is not specified)

#in base R, just use plot - when y is missing, barplot is produced
plot(fdata)

You can also plot in ggplot2

#in ggplot2
require(ggplot2)

#make a dataframe
df <- data.frame(id = seq(1:length(fdata)),
                 fdata = fdata)

#plot via geom_bar
ggplot(df, aes(fdata)) + geom_bar()

Proceeding from your original example, in addition to specifying levels, you are going to need to set ordered=TRUE as shown below. Otherwise, "No use" will still show up at the end of your list.

#get data into a factor (provided data plus "No use")
q1 <- c("No use"
        ,"1 hour"
        ,"1 hour"
        ,"30 min"
        ,"2 hours"
        ,"3+ hours"
        ,"3+ hours"
        ,"3+ hours"
        ,"3+ hours"
        ,"2 hours"
        ,"1 hour"
        ,"2 hours"
        ,"1 hour"
        ,"30 min")

q1f = factor(q1,
             levels = c("No use", 
                          "30 min", 
                          "1 hour", 
                          "2 hours", 
                          "3+ hours"),
             ordered=TRUE)

Then you can apply the plot logic shown above...

like image 33
joemienko Avatar answered Mar 25 '26 11:03

joemienko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!