Reputation: 107
Can someone help me generating a barplot with all the displayed properties and additionally with a different background color for each couple of bar?
SE are the error bars.
Mat <- matrix(c(1.97, 0.61, 0.06, 0.06, 0.61, 0.51, 0.03, 0.25, 2.25, 1.36, 0.15, 0.17, 1.19, 1.41, 0.04, 0.25),ncol=4,byrow=TRUE)
rownames(Mat) <- c("Cognitive Strategies","Motivational Strategies","SE Cognitive Strategies","SE Motivational Strategies")
colnames(Mat) <- c("No Problems","Motivational Problems","Knowledge Problems","Both Problems")
Mat <- as.data.frame(Mat)
barplot(as.matrix(Mat[1:2, 1:4]), main=NULL, ylab = "Number of \n motivational and cognitive Strateiges (CI 95%)", cex.lab = 1.5, cex.main = 1.4, beside=TRUE, col=c("darkblue","red"))
I do not know how to change the background color for every pair of bars and especially to put this in the same code with the error bars and the legend.
Upvotes: 1
Views: 4820
Reputation: 2399
Nadine,
first of all ggplot
likes data in long format. You can transform your data like following:
library(tidyverse)
library(wrapr)
Mat_long <-
Mat %>%
as_tibble() %>%
mutate(
Group = c('No Problems','Motivational Problems','Knowledge Problems','Both Problems'),
xpos = row_number()
) %>%
unite('Cognitive Strategies', c('Cognitive Strategies', 'SE Cognitive Strategies')) %>%
unite('Motivational Strategies', c('Motivational Strategies', 'SE Motivational Strategies')) %>%
gather(Type, val, `Motivational Strategies`:`Cognitive Strategies`) %>%
separate(val, c('val', 'SE'), sep = '_') %>%
mutate_at(4:5, as.numeric)
Mat_long
looks like below:
A tibble: 8 x 5
Group xpos Type val SE
<chr> <int> <chr> <dbl> <dbl>
1 No Problems 1 Motivational Strategies 0.61 0.06
2 Motivational Problems 2 Motivational Strategies 0.51 0.25
3 Knowledge Problems 3 Motivational Strategies 1.36 0.17
4 Both Problems 4 Motivational Strategies 1.41 0.25
5 No Problems 1 Cognitive Strategies 1.97 0.06
6 Motivational Problems 2 Cognitive Strategies 0.61 0.03
7 Knowledge Problems 3 Cognitive Strategies 2.25 0.15
8 Both Problems 4 Cognitive Strategies 1.19 0.04
Now you can do a beautifull plot like this:
with this code:
Mat_long %.>%
ggplot(
data = .,
aes(
x = xpos,
y = val,
fill = Type
)) +
geom_rect(aes(
xmin = xpos - .5,
xmax = xpos + .5,
ymin = -Inf,
ymax = Inf,
fill = Group
),
alpha = .2
) +
geom_col(
position = position_dodge(.5),
width = .5
) +
geom_errorbar(aes(
ymin = val - SE,
ymax = val + SE
),
position = position_dodge(.5),
width = .2
) +
geom_text(aes(
y = val + SE + .1,
label = val %>% str_replace('\\.', ',')
),
position = position_dodge(.5)
) +
scale_fill_manual(
values = c(
'#fb929e', # Both Problems
'#235784', # Cognitive Strategies
'#ffdfdf', # Knowledge Problems
'#fff6f6', # Motivational Problems
'#7a5d7e', # Motivational Strategies
'#aedefc' # No Problems
),
breaks = c(
'Cognitive Strategies',
'Motivational Strategies'
)
) +
scale_x_continuous(
breaks = .$xpos %>% unique(),
labels = .$Group %>% unique(),
expand = c(0, 0)
) +
scale_y_continuous(
labels = function(x) str_replace(x, '\\.', ','),
limits = c(0, 2.6),
expand = c(0, 0)
) +
ylab('Number of Motivational and Cognitive Strategies\n(CI 95%)') +
theme_light() +
theme(
legend.position = 'top',
legend.title = element_blank(),
legend.spacing.x = unit(1, 'mm'),
axis.title.x = element_blank()
)
But answer to your question is... You can do different background colors for each group with geom_rect
. The problem is geom_rect
needs numeric values. So you have to add number to each group (xpos
in my example) and later on change labels of x-axis with scale_x_continous
. You can pass down Mat_long
dataframe with wrapr
's %.>%
pipe, to use it later in scale_x_continous
by calling a dot .
:
scale_x_continuous(
breaks = .$xpos %>% unique(),
labels = .$Group %>% unique(),
...
)
Upvotes: 5
Reputation: 1252
No full answer, but a few hints:
For using ggplot, data must be in right shape (this might help: https://r4ds.had.co.nz/tidy-data.html). You can achieve this with gather()
from tidyverse library:
library (tidyverse)
plot_df <- gather(Mat, "Strategies", "Number")
plot_df$Problems <- factor(rep(rownames(Mat), 4), levels = rownames(Mat))
I'm using a factor for the "Problems" in order to being able to provide xmin and xmax values for the geom_rect
, which is used for drawing background to groups of bars:
ggplot(plot_df, aes(x = as.numeric(Problems), y = Number, fill = Strategies)) +
geom_rect(aes(xmin = as.numeric(Problems) - 0.4, xmax = as.numeric(Problems) + 0.4, ymin = 0, ymax = max(Number), fill = Problems), alpha = 0.2) +
geom_bar(stat = "identity", position = "dodge2") +
scale_x_continuous(labels = levels(plot_df$Problems), breaks = seq(1, length(unique(as.character(plot_df$Problems))))) +
xlab("Problems")
Don't look at the colours.... For adding errorbars see e.g. https://ggplot2.tidyverse.org/reference/geom_linerange.html
Upvotes: 2