I want to plot mean_1 and mean_2 separately by each value of grouping variable x.
Thus, I need two bars for each group.
Data:
n <- 100
set.seed(123)
data <- data.frame(
x = round(runif(n, min = 3, max = 5)),
mean_1 = rnorm(n, mean = 0, sd = 1),
mean_2 = rnorm(n, mean = 0, sd = 1) + 0.3)
Approach which just shows 1 bar:
library(ggplot2)
ggplot(data, aes(x = factor(x))) +
geom_bar(aes(y = mean_1), stat = "identity") +
geom_bar(aes(y = mean_2), stat = "identity") +
labs(x = "x",
y = "Abs") +
scale_fill_manual(values = c("blue", "red")) +
theme_minimal()
Thank you
>Solution :
You should first make your dataset tidy by using tidyr::pivot_longer (or any of your favorite reshaping approaches) then use ggplot, with a few tweaks to your existing code (see below)
Data
data_long <- tidyr::pivot_longer(data, mean_1:mean_2,
names_to = "mean",
values_to = "value")
# x mean value
# <dbl> <chr> <dbl>
# 1 4 mean_1 0.253
# 2 4 mean_2 1.09
# 3 5 mean_1 -0.0285
# 4 5 mean_2 1.07
# ....
To plot, use y = value and fill = mean in the aes(), as well as position = position_dodge() in geom_bar:
ggplot(data_long, aes(x = factor(x), y = value, fill = mean)) +
geom_bar(stat = "identity", position = position_dodge()) +
labs(x = "x",
y = "Abs") +
scale_fill_manual(values = c("blue", "red")) +
theme_minimal()
The above plot shows the range of mean_1 and mean_2, so if that’s the goal of visualization you are all set. Though, with these data, you may be better off using geom_boxplot, which shows several summary statistics by group via the box, whiskers, and points:
ggplot(data_long, aes(x = factor(x), y = value, fill = mean)) +
geom_boxplot() +
labs(x = "x",
y = "Abs") +
scale_fill_manual(values = c("blue", "red")) +
theme_minimal()
As @AllanCameron mentions, you may want to look into ... + geom_bar( stat = "summary", fun = mean, ...) + ..., which calculates and graphs the mean of each mean_1 and mean_2:
ggplot(data_long, aes(x = factor(x), y = value, fill = mean)) +
geom_bar(stat = "summary", fun = mean, position = position_dodge()) +
labs(x = "x", y = "Abs") +
scale_fill_manual(values = c("blue", "red")) +
theme_minimal()
Which produces the following plot:


