I had a similar problem as in this post , and the solution almost worked for my data, but I'm having problems to connect the points to the lines when I add jitter. I addeded jitter to the geom_point (position = "jitter") component as my individual points were overlapping in the bars, but now my individual lines are not connecting to the points. Does anyone have any suggestion on how to approach the problem? I already tried to create jitter in the dataframe values, but it didn't work either.
I tried the code below expecting to have the individual points connected to the lines, but it didn't work.
I also tried adding an interaction in x, but it also didn't work.
library(ggplot2)
df <- data.frame(
Group = c("A", "A", "A", "A", "B", "B"),
Subgroup = c("A.1", "A.2", "A.1", "A.2", "B.1", "B.2"),
Value = c(10, 7, 8, 9, 11, 12),
Pair = c(1, 1, 2, 2, 3, 3)
)
ggplot(df, aes(x = Subgroup, y = Value, fill = Subgroup)) +
geom_bar(stat = "summary", fun = "mean", width = 1) +
geom_point(position="jitter") +
geom_line(aes(group = Pair), color = "red", ) +
facet_wrap(vars(Group), scales = "free_x", strip.position = "bottom") +
labs(x = "Group") +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.background = element_blank(),
panel.spacing = unit(0, units = "line")
)
Edit = worked when implementing position = position_jitter(seed = 1) in both geom_line and geom_point. But unfortunately for my data it still don't work.
My dataframe:
tdcs_cer <- as.data.frame(structure(list(Subject = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5,
5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, 13, 17, 17,
17, 17, 17, 17, 17, 17, 17, 21, 21, 21, 21, 21, 21, 21, 21, 21,
25, 25, 25, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, 29, 29, 29,
29, 29, 33, 33, 33, 33, 33, 33, 33, 33, 33, 37, 37, 37, 37, 37,
37, 37, 37, 37, 41, 41, 41, 41, 41, 41, 41, 41, 41, 45, 45, 45,
45, 45, 45, 45, 45, 45, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53,
53, 53, 53, 53, 53, 53, 53, 53, 57, 57, 57, 57, 57, 57, 57, 57,
57, 61, 61, 61, 61, 61, 61, 61, 61, 61, 65, 65, 65, 65, 65, 65,
65, 65, 65, 77, 77, 77, 77, 77, 77, 77, 77, 77, 81, 81, 81, 81,
81, 81, 81, 81, 81, 89, 89, 89, 89, 89, 89, 89, 89, 89), Group = c("cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum",
"cerebellum", "cerebellum", "cerebellum", "cerebellum", "cerebellum"
), Music = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0), StimType = structure(c(2L, 2L, 2L, 3L,
3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L,
2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L,
2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L,
1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L,
3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L,
3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L,
2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L,
1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L,
1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L,
3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L,
2L, 3L, 3L, 3L, 1L, 1L, 1L), levels = c("Sham", "Anodal", "Cathodal"
), class = "factor"), condition = structure(c(2L, 1L, 3L, 2L,
1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L,
3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L,
2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L,
1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L,
3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L,
2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L,
1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L,
3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L,
2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L,
1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L,
3L, 2L, 1L, 3L, 2L, 1L, 3L), levels = c("Strong Beat", "Weak Beat",
"Non-Beat"), class = "factor"), TrialPassnum = c(1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0,
1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 1, NA, NA, NA,
NA), n = c(3, 8, 3, 1, 10, 20, 1, 3, 2, 3, 10, 2, 2, 4, 1, 2,
9, 1, 1, 10, 3, 3, 12, 2, 4, 15, 4, 9, 18, 6, 4, 11, 4, 6, 14,
3, 2, 7, 1, 1, 3, 2, 20, 7, 20, 6, 12, 1, 5, 11, 4, 7, 13, 1,
6, 16, 1, 5, 18, 3, 3, 14, 4, 1, 1, 20, 20, 20, 20, 2, 20, 20,
2, 7, 3, 2, 11, 2, 5, 12, 2, 20, 6, 1, 20, 4, 20, 20, 4, 1, 20,
2, 1, 20, 3, 1, 20, 20, 20, 1, 5, 2, 1, 9, 1, 1, 4, 1, 9, 19,
6, 2, 18, 1, 3, 14, 6, 1, 20, 20, 1, 5, 20, 2, 10, 20, 2, 13,
1, 2, 11, 2, 4, 15, 1, 7, 16, 5, 1, 8, 2, 6, 15, 7, 4, 14, 4,
4, 15, 2, 3, 12, 2, 1, 7, 1, 4, 14, 1, 1, 9, 2, 6, 4, 1, 20,
2, 20, 20, 20, 20), PropCorr = c(15, 40, 15, 5, 50, 0, 5, 15,
10, 15, 50, 10, 10, 20, 5, 10, 45, 5, 5, 50, 15, 15, 60, 10,
20, 75, 20, 45, 90, 30, 20, 55, 20, 30, 70, 15, 10, 35, 5, 5,
15, 10, 0, 35, 0, 30, 60, 5, 25, 55, 20, 35, 65, 5, 30, 80, 5,
25, 90, 15, 15, 70, 20, 5, 5, 0, 0, 0, 0, 10, 0, 0, 10, 35, 15,
10, 55, 10, 25, 60, 10, 0, 30, 5, 0, 20, 0, 0, 20, 5, 0, 10,
5, 0, 15, 5, 0, 0, 0, 5, 25, 10, 5, 45, 5, 5, 20, 5, 45, 95,
30, 10, 90, 5, 15, 70, 30, 5, 0, 0, 5, 25, 0, 10, 50, 0, 10,
65, 5, 10, 55, 10, 20, 75, 5, 35, 80, 25, 5, 40, 10, 30, 75,
35, 20, 70, 20, 20, 75, 10, 15, 60, 10, 5, 35, 5, 20, 70, 5,
5, 45, 10, 30, 20, 5, 0, 10, 0, 0, 0, 0)), row.names = c(NA,
-171L), class = c("tbl_df", "tbl", "data.frame")))
My code for my figure:
My_Theme = theme(
title = element_text(size = 15),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.title.y = element_text(size = 16),
axis.text.y = element_text(size = 15),
strip.text.y = element_blank(),
strip.text = element_text(size=15),
strip.background = element_blank(),
strip.placement = "outside",
axis.ticks.x = element_blank(),
axis.line.x = element_line(linetype="solid"),
legend.text = element_text(size = 13))
cer_plot <- ggplot(tdcs_cer, aes(x=StimType, y = PropCorr, fill = StimType)) +
geom_bar(stat = "summary", fun = "mean", width = 0.6, size=0.5, alpha=0.9) +
stat_summary(fun.data = mean_se, geom = "errorbar", width=0.3, size = 0.5, alpha = 0.4) +
geom_point(aes(x=StimType,y=PropCorr, color=StimType), size=2.5,position = position_jitter(seed = 1)) +
scale_color_manual(values=c("lightgrey", "pink", 'cyan'))+
geom_line(aes(group = Subject), color = "antiquewhite3", size=0.6, alpha=0.5, position = position_jitter(seed = 1)) +
facet_wrap(vars(condition), scales = "free_x", strip.position = "bottom") +
scale_fill_manual(values = c("Sham" = "darkgrey",
"Anodal" = "brown1",
"Cathodal" = "blue"))+
ggtitle("Right Cerebellum") +
labs(x = "", y = "Percent Correct")+
theme_classic()+
My_Theme
You have to use position_jitter
in geom_line
too and set the same random seed via the seed=
argument:
library(ggplot2)
ggplot(df, aes(x = Subgroup, y = Value, fill = Subgroup)) +
geom_bar(stat = "summary", fun = "mean", width = 1) +
geom_point(position = position_jitter(seed = 1)) +
geom_line(aes(group = Pair),
color = "red",
position = position_jitter(seed = 1)
) +
facet_wrap(vars(Group),
scales = "free_x",
strip.position = "bottom"
) +
labs(x = "Group") +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.background = element_blank(),
panel.spacing = unit(0, units = "line")
)
EDIT The issue with your real data and code is that the data for the geom_point
and the geom_line
are in a different order (Unfortunately I have no clue why). As a result the jittered points /lines will not align. The only option I have figured out to fix that is to manually jitter StimType
and PropCorr
outside of ggplot
and to use the jittered values for both layers.
library(ggplot2)
tdcs_cer$StimType1 <- jitter(
as.numeric(factor(tdcs_cer$StimType)),
amount = .45
)
tdcs_cer$PropCorr1 <- jitter(
tdcs_cer$PropCorr,
amount = .45
)
ggplot(tdcs_cer, aes(x = StimType, y = PropCorr)) +
geom_bar(
aes(fill = StimType),
stat = "summary", fun = "mean",
width = 0.6, size = 0.5, alpha = 0.9
) +
stat_summary(
fun.data = mean_se, geom = "errorbar",
width = 0.3, size = 0.5, alpha = 0.4
) +
geom_point(
aes(
x = StimType1,
y = PropCorr1,
color = StimType
),
size = 2.5
) +
geom_line(
aes(
x = StimType1,
y = PropCorr1,
group = Subject
),
color = "antiquewhite3",
size = 0.6, alpha = 0.5
) +
facet_wrap(vars(condition),
scales = "free_x",
strip.position = "bottom"
) +
scale_fill_manual(values = c(
"Sham" = "darkgrey",
"Anodal" = "brown1",
"Cathodal" = "blue"
)) +
scale_color_manual(
values = c("lightgrey", "pink", "cyan")
) +
ggtitle("Right Cerebellum") +
labs(x = "", y = "Percent Correct") +
theme_classic() +
My_Theme