I have the following code. How can I make the grid much finer scale? Also not sure why the legend is not showing? Like I want to have 4 o 8 squares between 75 and 100.
#Select the colors from http://colorbrewer2.org/#type=sequential&scheme=RdPu&n=9
if( !is.element("ggplot2", installed.packages()[,1]) )
install.packages("ggplot2")
if( !is.element("grid", installed.packages()[,1]) )
install.packages("grid")
if( !is.element("plyr", installed.packages()[,1]) )
install.packages("plyr")
if( !is.element("data.table", installed.packages()[,1]) )
install.packages("data.table")
if( !is.element("igraph", installed.packages()[,1]) )
install.packages("igraph")
if( !is.element("ggthemes", installed.packages()[,1]) )
install.packages("ggthemes")
library(ggplot2)
library(grid)
library(plyr)
library(data.table)
library(igraph)
library(ggthemes)
#setwd(dir = "/home/sathya/Documents/coreset/rplots/fig/svm")
svmdata <- fread("ionosphere-smooth-ls-optim.dat")
#svmdata <- read.table("ionosphere-smooth-ls-optim.dat", header=TRUE)
svmdata <- rename(svmdata, c("# k"="k"))
svmdata <- head(svmdata, 100)
svmdata_ls <- fread("ionosphere-ls-optim.dat")
svmdata_ls <- head(svmdata_ls,100)
svmdata_ls <- rename(svmdata_ls, c("# k"="k"))
y_max <- max(max(svmdata$gap), max(svmdata_ls$gap))
base <- ggplot(data=svmdata_ls,aes(x=k, y=gap, group=2)) +
geom_line(colour="#dd3497", size=1.5) + #geom_point(size=4, shape=21) +
geom_line(data=svmdata,aes(x=k, y=gap, group=1 ), colour="#54278f", size=1.5) +
#ggtitle("svmdata_ls gap and svmdata gap vs k") +
geom_smooth(alpha=.2, size=1) +
geom_abline(colour = "grey50", size = 2) +
xlim(0, max(svmdata$k)) +
ylim(0, y_max) +
scale_colour_manual("",
breaks = c("svmdata_ls", "svmdata"),
values = c("#dd3497", "#54278f"))
labelled <- base +
labs(
x = "K",
y = "Gap",
colour = "Cylinders",
title = "svmdata_ls gap and svmdata gap vs k"
)
labelled
styled <- labelled +
theme_bw() +
theme(
plot.title = element_text(face = "bold", size = 25, colour = "purple"),
axis.title=element_text(size= 20, face= "bold", colour="blue"),
legend.background = element_rect(fill = "white", size = 4, colour = "white"),
legend.justification = c(0, 1),
legend.key = element_rect(fill = "yellow"),
#legend.position = "bottom",
legend.position = c(0, 1),
axis.ticks = element_line(colour = "grey70", size = 0.25),
panel.grid.major = element_line(colour = "grey70", size = 0.5),
panel.grid.minor = element_line(colour= "grey70", size=0.5)
)
styled
Data: http://pastebin.com/0wb6S4m8 and http://pastebin.com/L4sdEyYZ
These are just the basics; I didn't bother with all the special colours etc..
to get a legend, combine your data into one long data frame and use aes(colour=grp), where grp is a variable that identifies the group.
to get finer-spaced tick marks, use scale_x_continuous() with breaks or minor_breaks set.
Get data:
rr <- function(x) plyr::rename(as.data.frame(data.table::fread(x)),
c("# k"="k"))
svmdata <- rr("ionosphere-smooth-ls-optim.dat")
svmdata_ls <- rr("ionosphere-ls-optim.dat")
Combine data into a single labeled data frame:
get_vars <- function(d) d[c("k","gap")]
svmcomb <- plyr::ldply(list(svmdata=svmdata,svmdata_ls=svmdata_ls),
get_vars)
Plot:
library(ggplot2)
ggplot(svmcomb,aes(k,gap,colour=.id))+
geom_line()+
scale_x_continuous(minor_breaks=seq(0,100,by=2.5))
Typically with ggplot you would approach this type of thing more like this:
svmdata$grp <- "svmdata"
svmdata_ls$grp <- "svmdata_ls"
dat <- rbind(svmdata,svmdata_ls)
base <- ggplot(data=dat,aes(x=k, y=gap, colour = grp,group=grp)) +
geom_line(size=1.5) + #geom_point(size=4, shape=21) +
geom_line(size=1.5) +
#ggtitle("svmdata_ls gap and svmdata gap vs k") +
geom_smooth(alpha=.2, size=1) +
geom_abline(colour = "grey50", size = 2) +
xlim(0, max(svmdata$k)) +
ylim(0, y_max) +
scale_colour_manual("",
breaks = c("svmdata_ls", "svmdata"),
values = c("#dd3497", "#54278f"))
Related
I am trying to display some graphs in a 1x4 grid, but I would like all the graphs to have the same x and y axes.
time maxhgs.sleep_LIPA maxhgs.sed_LIPA maxhgs.stand_LIPA maxhgs.MVPA_LIPA maxhgs.LIPA_MVPA
1 5 0.08289621 0.03241295 0.1129983 0.112998341 -0.01928050
2 10 0.16289049 0.06139545 0.2236818 -0.006728721 -0.04950022
3 15 0.24025861 0.08721203 0.3323473 -0.047756360 -0.08927656
4 20 0.31524160 0.11009218 0.4392581 -0.144261526 -0.13791276
5 25 0.38805152 0.13023596 0.5446498 -0.424789999 -0.19517306
6 30 0.41660977 0.13756729 0.5864293 -0.934884300 -0.26117695
This is the data I am working with.
library(ggplot2)
library(egg)
maxhgs.a <- ggplot(maxhgs.df, aes(time, maxhgs.sleep_LIPA)) + geom_point()+geom_line()
maxhgs.a <- maxhgs.a + scale_x_continuous(name = "Time Reallocated", breaks = seq(5,30, by=5)) +
scale_y_continuous(name = "Change in maxhgs", breaks = seq(0,1, by=0.1))+
ggtitle("Sleep to LIPA")
maxhgs.b <- ggplot(maxhgs.df, aes(time, maxhgs.sed_LIPA)) + geom_point()+geom_line()
maxhgs.b <- maxhgs.b + scale_x_continuous(name = "Time Reallocated", breaks = seq(5,30, by=5)) +
scale_y_continuous(name = "Change in maxhgs", breaks = seq(0,1, by=0.1))+
ggtitle("Sedentary to LIPA")
maxhgs.c <- ggplot(maxhgs.df, aes(time, maxhgs.stand_LIPA)) + geom_point()+geom_line()
maxhgs.c <- maxhgs.c + scale_x_continuous(name = "Time Reallocated", breaks = seq(5,30, by=5)) +
scale_y_continuous(name = "Change in maxhgs", breaks = seq(0,1, by=0.1))+
ggtitle("Standing to LIPA")
maxhgs.d <- ggplot(maxhgs.df, aes(time, maxhgs.MVPA_LIPA)) + geom_point()+geom_line()
maxhgs.d <- maxhgs.d + scale_x_continuous(name = "Time Reallocated", breaks = seq(5,30, by=5)) +
scale_y_continuous(name = "Change in maxhgs", breaks = seq(0.5,-1, by=-0.1))+
ggtitle("MVPA to LIPA")
ggarrange(maxhgs.a,
maxhgs.b +
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() ),
maxhgs.c +
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() ),
maxhgs.d +
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() ),
nrow = 1)
This is what I have attempted so far. This actually "works" in that all the graphs have the same y-axis, but the y-axis doesn't actually reflect what should be on the graphs. As you can see in the graph, the y-axis goes from 0.1 to 0.4, but the maxhgs.d graph should extend from 0.1 to -0.9.
Any advice or suggestions would be greatly appreciated!
You can make this much easier by reshaping your data and using faceting. That way, you only need to define a single plot. This requires you to pivot_longer and change the factor levels to the names you want for each facet, but once this is done, the plot itself is straightforward:
library(ggplot2)
library(dplyr)
# Define the label names for the facets first
labs <- c("LIPA to MVPA", "MVPA to LIPA", "Sedentary to LIPA",
"Sleep to LIPA", "Standing to LIPA")
gg <- maxhgs.df %>%
tidyr::pivot_longer(cols = -1) %>%
mutate(plot = factor(`levels<-`(factor(name), labs), labs[c(4, 3, 5, 2, 1)])) %>%
ggplot(aes(x = time, y = value)) +
geom_line() +
geom_point() +
scale_x_continuous(name = "Time Reallocated") +
scale_y_continuous(name = "Change in maxhgs") +
theme(strip.background = element_blank(),
strip.text = element_text(size = 13))
Now we can either choose to plot with fixed y axes:
gg + facet_grid(.~plot, scale = "fixed")
or with flexible y axes:
gg + facet_wrap(.~plot, scale = "free_y", ncol = 5)
Created on 2020-08-04 by the reprex package (v0.3.0)
I've three replicates of my experimental sample(F) and three replicates of control samples(C). Each experimental sample has 100 data points whereas each control has 70 data points. For the experimental data points, there are sub-categories like 4E,5E,7E,8E and for control there is only a single category CE.
Here's the code to generate some emulated data:
library(ggplot2)
set.seed(12345)
evals <- c( rep("4E",20), rep("5E",20), rep("7E",40), rep("8E",20))
subE <- c(sample(evals),sample(evals),sample(evals),rep("CE",70),rep("CE",70),rep("CE",70))
pwvr <- c(rnorm(100),rnorm(100),rnorm(100),rnorm(70,1.0),rnorm(70,1.1),rnorm(70,1.2))
expT <- c(rep("F",100*3),rep("C",70*3))
repX <- c(rep(1,100),rep(2,100),rep(3,100),rep(1,70),rep(2,70),rep(3,70))
myData.df <- data.frame(subE=as.factor(subE), pwvr = pwvr, expT= as.factor(expT), repX= as.factor(repX))
dim(myData.df)
What I want to do, is to draw Box and Jitter plots for the factor levels 4E,5E,7E,8E along with a boxplot of the combined values of these four levels. I don't know how to do that. Do I need to create another level clubbing all the corresponding values?
Secondly can anybody tell how to reorganize the appearance of orders in along the X-axis, like how to plot the following order 8E,7E,5E,4E etc.
The following code generates the plot for individual levels, but I need to have the box/jitter for the combined levels as well.
myGreen <- "forestgreen"
myBlue <- "dodgerblue2"
allboxCol <- c(rep(myGreen,1),rep(myBlue,1))
pw.boxplot <- ggplot(myData.df, aes(x=subE,y=pwvr, fill= expT)) +
geom_jitter(position=position_jitter(width=.2, height=0),alpha=0.15, aes(col= expT)) + scale_color_manual(values=allboxCol) +
geom_boxplot(outlier.shape = NA, fatten = 0.01, lwd=1.0,alpha=0.5,width=0.6) +
theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"))
pw.boxplot + scale_fill_manual(values=allboxCol) + facet_grid( .~ expT + repX , scales="free", space = "free" )
do you mean?
myGreen <- "forestgreen"
myBlue <- "dodgerblue2"
allboxCol <- c(rep(myGreen,1),rep(myBlue,1))
allboxCol <- c(alpha(allboxCol, 0.2),allboxCol[2])
library(tidyverse)
myData.df %>%
as_tibble() %>%
mutate(subE = paste0("total_", expT, repX)) %>%
filter(expT != "C") %>%
bind_rows(myData.df) %>%
mutate(fill = ifelse(grepl("total", subE), paste0("total_",expT), expT)) %>%
ggplot(aes(x=subE,y=pwvr, fill= fill)) +
geom_jitter(position=position_jitter(width=.2, height=0),alpha=0.15, aes(col= fill), show.legend = F) +
geom_boxplot(outlier.shape = NA, fatten = 0.01, lwd=1.0,width=0.6, show.legend = F) +
scale_fill_manual(values=allboxCol) +
scale_color_manual(values=allboxCol) +
theme_bw() +
theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "black")) +
facet_grid( .~ expT + repX , scales="free", space = "free" )
It is indeed an easy solution to just repeat the data but assigning a new level, I called it all. You can explicitly specify the order of the levels:
library(ggplot2)
library(dplyr)
set.seed(12345)
evals <- c( rep("4E",20), rep("5E",20), rep("7E",40), rep("8E",20))
subE <- c(sample(evals),sample(evals),sample(evals),rep("CE",70),rep("CE",70),rep("CE",70))
pwvr <- c(rnorm(100),rnorm(100),rnorm(100),rnorm(70,1.0),rnorm(70,1.1),rnorm(70,1.2))
expT <- c(rep("F",100*3),rep("C",70*3))
repX <- c(rep(1,100),rep(2,100),rep(3,100),rep(1,70),rep(2,70),rep(3,70))
myData.df <- data.frame(subE=subE, pwvr = pwvr, expT= expT, repX= repX,
stringsAsFactors = FALSE)
add_data <- myData.df %>%
filter(subE != "CE") %>%
mutate(subE = "all")
myData.df <- bind_rows(myData.df, add_data)
myData.df <- myData.df %>%
mutate(subE = as.factor(subE),
subE = factor(subE, levels = levels(subE)[c(4, 3, 2, 1, 5, 6)]))
myGreen <- "forestgreen"
myBlue <- "dodgerblue2"
allboxCol <- c(rep(myGreen,1),rep(myBlue,1))
pw.boxplot <- ggplot(myData.df, aes(x=subE,y=pwvr, fill= expT)) +
geom_jitter(position=position_jitter(width=.2, height=0),alpha=0.15, aes(col= expT)) + scale_color_manual(values=allboxCol) +
geom_boxplot(outlier.shape = NA, fatten = 0.01, lwd=1.0,alpha=0.5,width=0.6) +
theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"))
pw.boxplot + scale_fill_manual(values=allboxCol) + facet_grid( .~ expT + repX , scales="free", space = "free" )
Hello everyone I was trying to add some text below the x axis in ggplot2 and I was able to do so using geom_textand with help of coord_cartesian but I couldn't make it reproducible as this need to run in a loop. I thought that adding the values I want with the row names (First, Second) in a table would fix it, does anybody have experience in that. below is the workaround I did. Thank you very much in advance.
## Data
Grade <- 1 : 20
Case <- rep(paste('case' , 1:5,sep = ''),4)
Number <- paste('n', 1:20 , sep = '')
Class <- c(rep('Class1',5) , rep('Class2',5) , rep('Class3',5) , rep('Class4',5))
se <- 0.2
df <- data.frame(Grade,Case ,Number, Class , se)
## plot
ggplot(df, aes(x= factor(Case , levels = c('case1','case2' , 'case3' , 'case4','case5')) , y=Grade ,
fill= Grade)) +
geom_bar(position="dodge", stat="identity",
colour="black",
size=.4) +
geom_errorbar(aes(ymin=Grade +se, ymax=Grade +se),
size=.3,
width=.2,
position=position_dodge(.9))+
geom_linerange(aes(ymin = Grade , ymax = Grade +se),position=position_dodge(.9))+
geom_text(aes(label=Number , y = Grade + se + 1),data=df, position=position_dodge(0.9), size= 4) +
ggtitle('Place a table below x axis')+
facet_grid(~Class) +
xlab('') +
ylab('Case Num') +
theme_gray()+
theme(plot.margin = unit(c(1,1,1,6), "lines"),
axis.text.x = element_text(size = 15)) +
scale_x_discrete(labels = paste(1:5 , '\n' , 10:15, sep = '')) +
geom_text(data = df[df$Class == 'Class1',],x = -1 , y = -3,
label= 'First\nSecond' , size = 4)+
coord_cartesian(clip = "off" , xlim = c(1, 5) )
EDIT:
Sorry for the confusion,although the solution suggested by #stefan is pretty much convenient but the main purpose is to have something like this:
considering that the proposed table will contain external characters, not taken from the data frame at all (if possible!).
As an alternative approach to tackle this problem I simply set up the table as a second ggplot which I glue together with the major ggplot using patchwork.
## Data
Grade <- 1 : 20
Case <- rep(paste('case' , 1:5,sep = ''),4)
Number <- paste('n', 1:20 , sep = '')
Class <- c(rep('Class1',5) , rep('Class2',5) , rep('Class3',5) , rep('Class4',5))
se <- 0.2
df <- data.frame(Grade,Case ,Number, Class , se)
library(patchwork)
library(ggplot2)
library(tidyr)
library(dplyr)
## plot
p1 <- ggplot(df, aes(x= factor(Case , levels = c('case1','case2' , 'case3' , 'case4','case5')) , y=Grade ,
fill= Grade)) +
geom_bar(position="dodge", stat="identity",
colour="black",
size=.4) +
geom_errorbar(aes(ymin=Grade +se, ymax=Grade +se),
size=.3,
width=.2,
position=position_dodge(.9))+
geom_linerange(aes(ymin = Grade , ymax = Grade +se),position=position_dodge(.9))+
geom_text(aes(label=Number , y = Grade + se + 1),data=df, position=position_dodge(0.9), size= 4) +
ggtitle('Place a table below x axis')+
facet_grid(~Class) +
xlab(NULL) +
ylab('Case Num') +
theme_gray()+
theme(axis.text.x = element_blank())
p2 <- df %>%
mutate(First = as.integer(stringr::str_extract(Case, "\\d")),
Second = First + 9,
Third = Second + 9) %>%
pivot_longer(c(First, Second, Third), names_to = "layer", values_to = "label") %>%
ggplot(aes(x = Case)) +
geom_text(aes(y = factor(layer, c("Third", "Second", "First")), label = label)) +
labs(y = "", x = NULL) +
theme_minimal() +
theme(axis.line = element_blank(), axis.ticks = element_blank(), axis.text.x = element_blank(),
panel.grid = element_blank(), strip.text = element_blank()) +
facet_grid(~Class)
p1 / p2 + plot_layout(heights = c(8, 1))
Created on 2020-05-23 by the reprex package (v0.3.0)
EDIT: Tweak to get a more table like output by adding a geom_tile and removing the spacing between facets as well as setting expansion of x-axis to zero:
p2 <- df %>%
select(Case, Class) %>%
mutate(First = letters[1:nrow(.)],
Second = LETTERS[1:nrow(.)],
Third = as.character(1:nrow(.))) %>%
pivot_longer(c(First, Second, Third), names_to = "layer", values_to = "label") %>%
ggplot(aes(x = Case, y = factor(layer, c("Third", "Second", "First")))) +
# Add Table Style
geom_tile(fill = "blue", alpha = .4, color = "black") +
geom_text(aes(label = label)) +
# Remove expansion of axsis
scale_x_discrete(expand = expansion(mult = c(0, 0))) +
labs(y = "", x = NULL) +
theme_minimal() +
theme(axis.line = element_blank(), axis.ticks = element_blank(), axis.text.x = element_blank(),
panel.grid = element_blank(), strip.text = element_blank(), panel.spacing.x = unit(0, "mm")) +
facet_grid(~Class)
p1 / p2 + plot_layout(heights = c(8, 1))
Created on 2020-05-24 by the reprex package (v0.3.0)
If I understand your requirement correctly, (as in my comment above), this may help you. You just need to name your graph and add the labels in loop and render outside the loop.
...
theme(plot.margin = unit(c(1,1,1,6), "lines"),
axis.text.x = element_text(size = 15)) +
scale_x_discrete(labels = paste(1:5 , '\n' , 10:15, sep = '')) +
coord_cartesian(clip = "off" , xlim = c(1, 5) )
label = NULL
ordinal <- c('first','second','third','fourth','fifth','sixth','seventh','eighth','ninth','tenth')
for (i in 1:5) {
label <- paste(label, '\n', ordinal[i])
}
g1 <- g1 + geom_text(data = df[df$Class == 'Class1',],x = -1 , y = -3,
label= label , size = 4)
g1
This is what I get as a result:
I am looking for a method, using ggplot2 or grid, to make a chart like the one below. I can recreate this in Tableau, but am not sure where to begin (data setup, packages) to do so in R. Any help recreating this would be great! I am hoping to use a chart like this in the future.
You can try working with this function.
four_quadrant <- function(x, col_quad="gray65", col_text="white") {
nx <- length(x)
sqx <- sqrt(x)
df <- data.frame(x=c(sqx[1],-sqx[2],-sqx[3],sqx[4])/2,
y=c(sqx[1],sqx[2],-sqx[3],-sqx[4])/2,
size=sqx, label=x)
mm <- max(df$size)*1.1
ggplot(data=df, aes(x=x, y=y, width=size, height=size,
group=factor(size))) +
geom_tile(fill=col_quad) +
geom_text(aes(label=label), col=col_text, size=5) +
geom_hline(aes(yintercept=0), size=0.8) +
geom_vline(aes(xintercept=0), size=0.8) +
coord_fixed() +
xlim(c(-mm,mm)) + ylim(c(-mm,mm)) +
theme_void() +
theme(legend.position = "none")
}
x <- c(18, 54, 5, 15)
p1 <- four_quadrant(x)
x <- c(30, 17, 6, 34)
p2 <- four_quadrant(x, col_quad="salmon")
gridExtra::grid.arrange(p1, p2, nrow=1)
You can rather easily do it with ggplot using geom_rect. I've created a mock up data of the first chart to show you how to create one plot. You can reuse this to create the others and put them together using grid (there are loads of examples on SO how to do this).
library(tidyverse)
df <- data.frame(perc = c(54, 18, 5, 15),
wall_policy = c("oppose", "favor", "oppose", "favor"),
dreamer_policy = c("favor", "favor", "oppose", "oppose"),
stringsAsFactors = FALSE)
df <- df %>%
mutate(xmin = if_else(wall_policy == "oppose", -sqrt(perc), 0),
xmax = if_else(wall_policy == "favor", sqrt(perc), 0),
ymin = if_else(dreamer_policy == "oppose", -sqrt(perc), 0),
ymax = if_else(dreamer_policy == "favor", sqrt(perc), 0))
ggplot(df) +
geom_rect(aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax), fill = "grey") +
geom_text(aes(x = xmin + 0.5*sqrt(perc),
y = ymin + 0.5*sqrt(perc),
label = perc),
color = "white", size = 10) +
coord_equal() +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0) +
labs(title = "Total") +
theme_minimal() +
theme(axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.title = element_text(color="grey40", face="bold",
size=20, hjust = 0.5))
I have a dataset in which I have two groups that underwent test and retest measurements. I created a figure displaying four boxplots (groups x tests) with points for each measurement. Test and retest scores are connected by a line for each subject and the boxplots are colored according to the test or retest session.
Now I would like to fill or un-fill the boxplots according to the group. I have create the figure below by creating two figures (filled and unfilled) by switching the geom_boxplot options in the code below and then merging them in photoshop. However, I was wondering if there is a way to create this figure completely with ggplot?
library(ggplot2)
group <- c("HC","HC","HC","HC","HC","HC","HC","HC","HC","HC","HC","HC","HC","HC","PAT","PAT","PAT","PAT","PAT","PAT","PAT","PAT","PAT","PAT")
session <- c("test","retest","test","retest","test","retest","test","retest","test","retest","test","retest","test","retest","test","retest","test","retest","test","retest","test","retest","test","retest")
value <- c(2,1.998521753,1.874733659,1.718486493,1.623289857,1.546827187,1.423472302,1.391178972,1.706069109,1.633178623,1.55107172,1.529644866,1.85152853,1.955804538,1.642797713,1.618263891,1.332975483,1.191228234,1.314644375,1.18511437,1.881207152,1.764699552,1,1.001585308)
index <- c(1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12)
df <- data.frame(group, session, value, index, U = interaction(session,group))
p <- ggplot(df, aes(x=U, y=value))
p <- p + geom_boxplot(aes(fill=session), data=df, colour="black", outlier.alpha=0.0, lwd=0.8, alpha=0.94)
# p <- p + geom_boxplot(aes(colour=session), data=df, outlier.alpha=0.0, lwd=0.8)
dat <- ggplot_build(p)$data[[1]]
p <- p + geom_segment(data=dat, aes(x=xmin, xend=xmax, y=middle, yend=middle), colour="grey70", size=1.6)
p <- p + stat_summary(fun.y=mean,geom="point",pch="-",colour="grey30",size=8, position = position_dodge(width=0.75))
p <- p + geom_line(aes(group = index), alpha = 0.7, colour ="grey50", data=df)
p <- p + geom_point(size=2, aes(group=session), colour="black", data=df, position = position_dodge(width=0.75))
p <- p + scale_x_discrete(labels=c("HC-test","HC-retest","PAT-test","PAT-retest"))
p <- p + scale_y_continuous(limits=c(0.9,2.1), breaks=c(1,1.5,2))
p <- p + scale_colour_manual(values=c("#bf812d","#35978f"))
p <- p + scale_fill_manual(values=c("#bf812d","#35978f"))
p <- p + theme_bw()
p <- p + theme(
axis.text.x = element_text(colour = "black"),
axis.text.y = element_text(colour = "black"),
axis.title.x = element_blank(),
axis.title.y = element_text(colour = "black"),
legend.position = "none",
panel.border = element_rect(colour = "black", fill=NA, size=1)
)
p <- p + labs(y=expression("Normalized Volume(mm)"^3))
ggsave("~/Desktop/test.pdf", width=5, height=4, units=c("in"), plot=p)
You could try to set the factor order differently. You also need to specify sufficient number of values in scale_xxx_manual. I have stripped down the example to include the boxes only, because this was your focal issue.
df$session <- factor(df$session, levels = c("test", "retest"))
df$U = interaction(df$group, df$session, lex.order = TRUE)
ggplot(df, aes(x = U, y = value, fill = U, color = U)) +
geom_boxplot() +
scale_fill_manual(values = c("white", "white", "#bf812d", "#35978f"), guide = "none") +
scale_color_manual(values = c("#bf812d", "#35978f", "black", "black"), guide = "none")