Reputation: 64074
I have the following data which I want to plot with ggplot:
SC_LTSL_BM 16.8275
SC_STSL_BM 17.3914
proB_FrBC_FL 122.1580
preB_FrD_FL 18.5051
B_Fo_Sp 14.4693
B_GC_Sp 15.4986
What I want to do is to make a bar plot and maintain the order of the bar,
(i.e. starting with SC_LTSL_BM ...B_GC_Sp
). But the default behavior of
ggplot geom_bar is to sort them. How can I avoid that?
library(ggplot2)
dat <- read.table("http://dpaste.com/1469904/plain/")
pdf("~/Desktop/test.pdf")
ggplot(dat,aes(x=V1,y=V2))+geom_bar()
dev.off()
The current figure looks like this:
Upvotes: 97
Views: 111717
Reputation: 3417
As other answers have pointed out, ggplot wants you to specify a variable as a factor if you don't want it to presume the order to display things in. Using the readr
library is the easiest way to do this if you're working with data that has already been ordered.
Instead of the read.table
function, use read_table
and as part of the col_types
argument, specify the column with the labels (V1
in this case) as a factor. For small datasets like this a simple format string is often the easiest way
dat <- read_table("http://dpaste.com/1469904/plain/", col_types = "fd")
The string "fd"
tells read_table
that the first column is a factor and the second column is a double. The help file for the function includes a character mapping for other types of data.
Upvotes: 0
Reputation: 16876
If you want to avoid changing the original data, then you can use fct_inorder
from forcats
(part of tidyverse
) to keep the original order of the data along the x-axis (rather than it being changed to alphabetical).
library(tidyverse)
ggplot(dat, aes(x = fct_inorder(V1), y = V2)) +
geom_bar(stat = "identity")
Output
Another option with forcats
is to manually specify the order with fct_relevel
.
ggplot(dat, aes(
x = fct_relevel(
V1,
"SC_LTSL_BM",
"SC_STSL_BM",
"proB_FrBC_FL",
"preB_FrD_FL",
"B_Fo_Sp",
"B_GC_Sp"
),
y = V2
)) +
geom_bar(stat = "identity") +
xlab("Category")
Data
dat <- structure(list(
V1 = c(
"SC_LTSL_BM",
"SC_STSL_BM",
"proB_FrBC_FL",
"preB_FrD_FL",
"B_Fo_Sp",
"B_GC_Sp"
),
V2 = c(16.8275, 17.3914,
122.158, 18.5051, 14.4693, 15.4986)
),
class = "data.frame",
row.names = c(NA, -6L))
Upvotes: 14
Reputation: 1242
Here is an approach that does not modify the original data, but uses scale_x_discrete
. From ?scale_x_discrete
, "Use limits to adjust the which levels (and in what order) are displayed". For example:
dat <- read.table(text=
"SC_LTSL_BM 16.8275
SC_STSL_BM 17.3914
proB_FrBC_FL 122.1580
preB_FrD_FL 18.5051
B_Fo_Sp 14.4693
B_GC_Sp 15.4986", header = FALSE, stringsAsFactors = FALSE)
# plot
library(ggplot2)
ggplot(dat,aes(x=V1,y=V2))+
geom_bar(stat="identity")+
scale_x_discrete(limits=dat$V1)
Upvotes: 53
Reputation: 1466
dplyr lets you easily create a row
column that you can reorder by in ggplot.
library(dplyr)
dat <- read.table("...") %>% mutate(row = row_number())
ggplot(df,aes(x=reorder(V1,row),y=V2))+geom_bar()
Upvotes: 10
Reputation: 3547
You can also just re-order the corresponding factor as described here
x$name <- factor(x$name, levels = x$name[order(x$val)])
Upvotes: 7
Reputation: 42343
You need to tell ggplot that you've got an ordered factor already, so it doesn't automatically order it for you.
dat <- read.table(text=
"SC_LTSL_BM 16.8275
SC_STSL_BM 17.3914
proB_FrBC_FL 122.1580
preB_FrD_FL 18.5051
B_Fo_Sp 14.4693
B_GC_Sp 15.4986", header = FALSE, stringsAsFactors = FALSE)
# make V1 an ordered factor
dat$V1 <- factor(dat$V1, levels = dat$V1)
# plot
library(ggplot2)
ggplot(dat,aes(x=V1,y=V2))+geom_bar(stat="identity")
Upvotes: 100