Reputation: 55
I was trying to create a bar plot by the order of stay
. I used reorder
and factor
but the order of bars in the plot did not change. Here is a reproducible example.
library(ggplot2)
speed <- c(300, 75, 100, 200, 150, 225, 75, 300, 150, 75, 200, 150, 225, 75, 350, 75, 300, 150, 150, 200, 225, 150, 75, 300, 100, 350, 100, 225, 350, 225, 150, 225, 200, 150)
stay <- c(0, runif(n = length(speed) - 1, min = 0, max = 25))
Vol <- c(0, 25, rnorm(n = length(speed) - 2, mean = -40, sd = 20))
Death <- sample(0:1, size = length(speed), replace = T)
fig.data <- data.frame(driver = 1:length(speed), speed = speed, stay = stay, Vol = Vol, Death = Death)
fig.data$speed <- as.factor(fig.data$speed)
# solution 1 (not work): use factor ------------------------------------------------------
# fig.data$driver <- factor(fig.data$driver, levels = order(-fig.data$stay))
# solution 2 (not work): use reorder -----------------------------------------------------
# fig.data$driver <- reorder(fig.data$driver, -fig.data$stay)
# solution 3 (work!): order the data frame -----------------------------------
# fig.data <- fig.data[order(-stay),]
I used the following code to produce ggplot
ggplot(data = fig.data, aes(x = driver, y = Vol)) +
geom_col(aes(fill = speed), width = 0.5) +
geom_point(data = fig.data %>% filter(Vol == 0),
shape = 4,
position = position_nudge(y = 0),
size = 2,
show.legend = FALSE) +
geom_hline(yintercept = round(mean(Vol), 0)) +
scale_x_discrete(limits = fig.data$driver,
breaks = fig.data$driver) +
scale_y_continuous(limits = c(-100, 100),
breaks = c(seq(-100,100,20), round(mean(fig.data$Vol), 0)),
minor_breaks = NULL) +
coord_flip() +
guides(fill = FALSE)
The first driver
has lowest stay
, and thus this bar should be at the top of the figure. For convenience, I marked this driver using "X". However, both solution 1 and 2 gave me this
What I expect is this, (use solution 3)
Did I misunderstand the first two solutions?
Update
After reviewed the posted question, I found the reason was I used limits = fig.data$driver
and breaks = fig.data$driver
in scale_x_discrete
. However, for solution 1, I should use limits = levels(fig.data$driver)
and breaks = levels(fig.data$driver)
.
Some related questions:
Upvotes: 0
Views: 2118
Reputation: 55
As suggested, I post my answer here.
After reviewed the posted question, I found the reason was I used limits = fig.data$driver
and breaks = fig.data$driver
in scale_x_discrete
. However, for solution 1, they should be limits = levels(fig.data$driver)
and breaks = levels(fig.data$driver)
.
Upvotes: 0
Reputation: 739
Do not use scale_x_discrete()
in the solution 1 and 2. By default, ggplot will order the axis labels according to the levels of the factor (if the axis is a factor). It will override the right order while using scale_x_discrete()
library(ggplot2)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
speed <- c(300, 75, 100, 200, 150, 225, 75, 300, 150, 75, 200, 150, 225, 75, 350, 75, 300, 150, 150, 200, 225, 150, 75, 300, 100, 350, 100, 225, 350, 225, 150, 225, 200, 150)
stay <- c(0, runif(n = length(speed) - 1, min = 0, max = 25))
Vol <- c(0, 25, rnorm(n = length(speed) - 2, mean = -40, sd = 20))
Death <- sample(0:1, size = length(speed), replace = T)
fig.data <- data.frame(driver = 1:length(speed), speed = speed, stay = stay, Vol = Vol, Death = Death)
fig.data$speed <- as.factor(fig.data$speed)
fig.data$driver <- factor(fig.data$driver, levels = order(-fig.data$stay))
ggplot(data = fig.data, aes(x = driver, y = Vol)) +
geom_col(aes(fill = speed), width = 0.5) +
geom_point(data = fig.data %>% filter(Vol == 0),
shape = 4,
position = position_nudge(y = 0),
size = 2,
show.legend = FALSE) +
geom_hline(yintercept = round(mean(Vol), 0)) +
# scale_x_discrete(limits = fig.data$driver,
# breaks = fig.data$driver) +
scale_y_continuous(limits = c(-100, 100),
breaks = c(seq(-100,100,20), round(mean(fig.data$Vol), 0)),
minor_breaks = NULL) +
coord_flip() +
guides(fill = FALSE)
Created on 2020-04-26 by the reprex package (v0.3.0)
Upvotes: 1