Hi I want to customize the plot to something like this:
-I want to have some straight line inside the plot and want to change the legend to something in the left side rather than the normal legend in right side. Also add some texts beside the variables (categorize). I have tried ggcorrplot, ggcorr, corrplot, ggplot to make this, but still can't find the solution. Anyone can help? Thanks.
Sample plot-How to make it?
ggcorr(data = NULL, cor_matrix = corr, nbreaks = 4, hjust = 1, size = 3,
color = "grey60", layout.exp = 1, legend.size = 8, name= "R", palette = "RdYlGn") +
labs(title = "Corr") +
theme(plot.title = element_text(size = 13)) +
theme(plot.title = element_text(size = 14, color="grey40"))
I found an example code on http://www.sthda.com/english/wiki/ggplot2-quick-correlation-matrix-heatmap-r-software-and-data-visualization hope you can be inspired:
library(reshape2)
library(ggplot2)
mydata <- mtcars[,c(1,3,4,5,6,7)]
cormat <- round(cor(mydata),2) # got correlation matrix
# Get lower triangle of the correlation matrix, we use upper for what you wanted
get_lower_tri<-function(cormat){
cormat[upper.tri(cormat)] <- NA
return(cormat)
}
# Get upper triangle of the correlation matrix
get_upper_tri <- function(cormat){
cormat[lower.tri(cormat)]<- NA
return(cormat)
}
upper_tri <- get_upper_tri(cormat)
melted_cormat <- melt(upper_tri, na.rm = TRUE)
ggheatmap <- ggplot(data = melted_cormat, aes(Var2, Var1, fill = value))+
geom_tile(color = "white")+
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1,1), space = "Lab",
name="Pearson\nCorrelation") +
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, vjust = 1,
size = 12, hjust = 1))+
coord_fixed()
ggheatmap +
theme(legend.justification = c(1, 0),
legend.position = c(0.3, 0.5))+
guides(fill = guide_colorbar(title.position = "top", title.hjust = 0.5))
themes()can help you to change the position and direction of legend.
finally you got:
mydata <- mtcars[,c(1,3,4,5,6,7)]
cormat <- round(cor(mydata),2)
cormat[lower.tri(cormat, diag = T)]<- 100
cormat <- melt(cormat, na.rm =F)
cormat[is.na(cormat)] <- 10
cormat[cormat$value != 100 ,] ->cormat
cormat$value[cormat$value == 10 ] <- NA
cormat$value[cormat$value >= 0.5 ] <- 1
cormat$value[cormat$value <= -0.5 ] <- -1
cormat$value[cormat$value > -0.5 & cormat$value < 0.5 ] <- 0
# Create a ggcorrx
dev.new(width=15, height=15)
gcorx <- ggplot(cormat, aes(Var2, Var1, fill = value, colour=""))+
geom_tile(color = "grey60")+
scale_fill_gradient2(breaks=c(-1,-0.5,0.5,1),low = "red", high = "green", mid =
"yellow", midpoint = 0, limit = c(-1,1), space = "Lab", name="Not ?? OK", na.value="black") +
theme_minimal()+ # minimal theme
theme(axis.text.x = element_text(angle = 50, vjust = 1,
size = 8, hjust = 1))+
theme(axis.text.y = element_text(vjust = 1,
size = 8, hjust = 1))+
scale_y_discrete(position = "right")+
scale_x_discrete()+
coord_fixed()+
ggtitle("MT CARS")+
geom_segment(aes(x=1.5,xend=5.5,y=2.5,yend=2.5), color="black", size=2)+
geom_segment(aes(x=1.5,xend=1.5,y=0.5,yend=2.5), color="black", size=2)+
annotate("text", x=0.7, y=2.5, label= "Part 1", size = 3, color="black",angle = 50,
fontface = "bold")+
annotate("text", x=2, y=4, label="Part 2", size = 3, color="black",angle = 50,
fontface = "bold")
gcorx +
theme(
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.major = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(color="black", size=12, face="bold", hjust = 0.5),
legend.justification = c(1, 0),
legend.position = c(0.3, 0.7),
legend.direction = "horizontal",
legend.title = element_text(size=9, face= "italic"))+
guides(fill = guide_colorbar(barwidth = 8, barheight = 1,title.position = "top",
title.hjust = 0.5))
Result:
But I still don't know to move label to diagonal. Anyone?
Related
I have a matrix that I already cut into the upper triangle:
eSim <- c(1,1,-1,-1,1,1,-1,-1,-1,-1,1,1,-1,-1,1,1)
dim(eSim) <- c(4,4)
rownames(eSim)=c("PosLong\n1200", "PosLong\n1800", "Neglong\n1200", "Neglong\n1800")
colnames(eSim)=c("PosLong\n1200", "PosLong\n1800", "Neglong\n1200", "Neglong\n1800")
# Get upper triangle of the correlation matrix
get_upper_tri <- function(cormat){
cormat[lower.tri(cormat)]<- NA
return(cormat)
}
eSim_upper <- get_upper_tri(eSim)
melted_eSim_upper <- melt(eSim_upper, na.rm = TRUE)
And this is my code for plotting this matrix
ggplot(data = melted_eSim_upper, aes(Var2, Var1, fill = as.factor(value)))+
geom_tile(color = "black", size=0.8)+
scale_fill_manual(values=c("#8DD3C7", "#FB8072"))+
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, vjust = 1,
size = 12, hjust = 1))+
theme(axis.text.y = element_text(angle = 45, vjust = 1,
size = 12, hjust = 1))+
coord_fixed()+
theme(axis.title.x = element_blank(),
axis.title.y = element_blank())+
theme(panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.border = element_blank())+
theme(axis.text.y = element_text(margin = margin(t = 0, r = 0, b = 0, l = 50)))
The outcome:
I have several questions to acheive my final goal:
Is there a way to rotate this plot diagnoally? Something like this:
Is there a way to move the y axis text further away to the matrix?
Yes, use limits = rev in a discrete scale.
Yes, but the more convenient thing to do is to use guide = guide_axis(angle = 45) instead of micromanaging the theme settings.
library(ggplot2)
eSim <- c(1,1,-1,-1,1,1,-1,-1,-1,-1,1,1,-1,-1,1,1)
dim(eSim) <- c(4,4)
rownames(eSim)=c("PosLong\n1200", "PosLong\n1800", "Neglong\n1200", "Neglong\n1800")
colnames(eSim)=c("PosLong\n1200", "PosLong\n1800", "Neglong\n1200", "Neglong\n1800")
# Get upper triangle of the correlation matrix
get_upper_tri <- function(cormat){
cormat[lower.tri(cormat)]<- NA
return(cormat)
}
eSim_upper <- get_upper_tri(eSim)
melted_eSim_upper <- reshape2::melt(eSim_upper, na.rm = TRUE)
ggplot(data = melted_eSim_upper, aes(Var2, Var1, fill = as.factor(value)))+
geom_tile(color = "black", size=0.8)+
scale_fill_manual(values=c("#8DD3C7", "#FB8072"))+
scale_y_discrete(limits = rev, guide = guide_axis(angle = 45)) +
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, vjust = 1,
size = 12, hjust = 1))+
theme(axis.text.y = element_text(size = 12))+
coord_fixed()+
labs(x = NULL, y = NULL) +
theme(panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.border = element_blank())
Created on 2022-09-19 by the reprex package (v2.0.1)
The function stat_pvalue_manual() will add p-values to boxplots using ggboxplot. However, the p-values that are printed are sometimes many digits long. I would like to limit the number of decimal places to 3. How can I do that?
From the plot below you will see that the p-value for versicolor and virginica is 5 decimal places, how can I adjust the code below to report back 3 decimal places (i.e., 0.009)?
library(ggplot2)
library(tidyverse)
library(dplyr)
library(rstatix)
library(ggpubr)
test <- iris
test$Species <- as.factor(test$Species)
test.aov <- test %>% anova_test(Sepal.Width ~ Species)
test.tukey <- test %>% tukey_hsd(Sepal.Width ~ Species)
test.tukey <- test.tukey %>% add_xy_position(x = "Species")
ggboxplot(test, x = "Species", y = "Sepal.Width", outlier.shape = NA) +
stat_pvalue_manual(test.tukey, hide.ns = TRUE, y.position = c(5,4.5,4), label = "p = {p.adj}") +
geom_jitter(shape=16, alpha = 0.4, size = 2, position=position_jitter(0.1)) +
labs(subtitle = get_test_label(test.aov, detailed = T)) +
scale_y_continuous(breaks = seq(0,5,1), limits = c(0,5)) +
xlab("Species") +
ylab("Sepal Length") +
theme_bw() +
theme(panel.grid = element_blank(),
plot.subtitle = element_text(vjust = -105, hjust = 0.05),
text = element_text(size = 14),
axis.text.x = element_text(size = 16, color = "black"),
axis.text.y = element_text(size = 16, color = "black"))
You could uselabel = "p = {scales::pvalue(p.adj)}"
ggboxplot(test, x = "Species", y = "Sepal.Width", outlier.shape = NA) +
stat_pvalue_manual(test.tukey, hide.ns = TRUE, y.position = c(5,4.5,4),
label = "p = {scales::pvalue(p.adj)}") +
geom_jitter(shape=16, alpha = 0.4, size = 2, position=position_jitter(0.1)) +
labs(subtitle = get_test_label(test.aov, detailed = T)) +
scale_y_continuous(breaks = seq(0,5,1), limits = c(0,5)) +
xlab("Species") +
ylab("Sepal Length") +
theme_bw() +
theme(panel.grid = element_blank(),
plot.subtitle = element_text(vjust = -105, hjust = 0.05),
text = element_text(size = 14),
axis.text.x = element_text(size = 16, color = "black"),
axis.text.y = element_text(size = 16, color = "black"))
I am trying to move the legend text and legend boxes further apart (horizontally) on a box and jitter plot. The complicating factor is the coord_flip I used to make the boxplot horizontal. In theme I tried using both legend.spacing.x and legend.spacing.y but neither had any effect on the distance between legend text and legend boxes.
Here is the graph with fake data. More complex than necessary I know but I need to be able to make it work with all the complications.
library(dplyr)
library(ggplot2)
set.seed(01234)
# make some data
totDays <- data.frame(id = 1:80,
group = rep(c("Placebo", "Drug"), each = 40),
total84 = c(pmin(abs(round(rnorm(40, 55, 30))),84), pmin(abs(round(rnorm(40, 38, 30))),84)))
# get some descriptives
(groupDF <- totDays %>% group_by(group) %>%
dplyr::summarise(m = mean(total84, na.rm = T),
sd = sd(total84, na.rm = T),
count = n()) %>%
mutate(se = sd/sqrt(count)))
# now for the box and scatter plot
(g <- ggplot(totDays, aes(group, total84, colour = group)) +
geom_jitter(size = 1, width = 0.1) + # so points aren't overlaid, width controls how much jitter
geom_point(stat = "summary", fun.y = "mean", shape = 3, size = 3, colour = "black") + # crosses for mean
geom_boxplot(alpha = 0, width = 0.5, lwd = 1, size = 0.5) +
scale_color_manual(values = c("#00AFBB", "#E7B800")) +
scale_y_continuous(breaks = seq(0,84,14), minor_breaks = seq(0, 84, 14)) + # changes minor break line
coord_flip() +
labs(y = "Score") +
geom_hline(yintercept = c(groupDF$m), linetype = "dotted") +
geom_segment(x = 2.38, xend = 2.38, y = groupDF$m[2] + .1, yend = groupDF$m[1] - .1, size = .7, arrow = arrow(end = "both", type = "open", length = unit(0.15, "cm")), colour = "#696969") +
annotate("text", x = 2.46, y = mean(groupDF$m), label = paste0("italic(p) == ", 0.02), parse = T) +
theme_bw() +
theme(axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(size = 13),
axis.title.x = element_text(size = 13, face = "bold", margin = margin(t = 0, r = 0, b = 10, l = 0), vjust = -2), # note the use of margin to move the title away from the axis text
legend.title = element_blank(),
legend.position = "top",
legend.spacing.y = unit(.1, "cm"),
legend.box.spacing = unit(.1, "cm"), # adjusts distance of box from x-axis
legend.key.size = unit(1, "cm"),
legend.text = element_text(size = 13, face = "bold"),
strip.text = element_text(size = 13, face = "bold"),
panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(size=.4, color="#F7F7F7")))
Use either stringr::str_pad() or theme(legend.spacing.x = ...) or both
g <- ggplot(totDays, aes(group, total84, colour = group)) +
geom_jitter(size = 1, width = 0.1) + # so points aren't overlaid, width controls how much jitter
geom_point(stat = "summary", fun.y = "mean", shape = 3, size = 3, colour = "black") + # crosses for mean
geom_boxplot(alpha = 0, width = 0.5, lwd = 1, size = 0.5) +
scale_color_manual(values = c("#00AFBB", "#E7B800"),
### added
labels = stringr::str_pad(c("Drug", "Placebo"), 10, "right")) +
scale_y_continuous(breaks = seq(0,84,14), minor_breaks = seq(0, 84, 14)) + # changes minor break line
coord_flip() +
labs(y = "Score") +
geom_hline(yintercept = c(groupDF$m), linetype = "dotted") +
geom_segment(x = 2.38, xend = 2.38, y = groupDF$m[2] + .1, yend = groupDF$m[1] - .1, size = .7,
arrow = arrow(end = "both", type = "open", length = unit(0.15, "cm")), colour = "#696969") +
annotate("text", x = 2.46, y = mean(groupDF$m), label = paste0("italic(p) == ", 0.02), parse = T) +
theme_bw() +
theme(axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(size = 13),
axis.title.x = element_text(size = 13, face = "bold",
margin = margin(t = 0, r = 0, b = 10, l = 0), vjust = -2),
legend.title = element_blank(),
legend.position = "top",
### added
legend.spacing.x = unit(0.25, 'cm'),
legend.spacing.y = unit(.1, "cm"),
legend.box.spacing = unit(.1, "cm"), # adjusts distance of box from x-axis
legend.key.size = unit(1, "cm"),
legend.text = element_text(size = 13, face = "bold"),
strip.text = element_text(size = 13, face = "bold"),
panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(size=.4, color="#F7F7F7"))
Created on 2019-03-11 by the reprex package (v0.2.1.9000)
Hi this is actually follow up question from my previous question here:
Customize correlation plot r
So I still can not move the label to diagonal side and change the colour scale to discrete scale like below (sample):
And here my code so far:
mydata <- mtcars[,c(1,3,4,5,6,7)]
cormat <- round(cor(mydata),2)
cormat[lower.tri(cormat, diag = T)]<- 100
cormat <- melt(cormat, na.rm =F)
cormat[is.na(cormat)] <- 10
cormat[cormat$value != 100 ,] ->cormat
cormat$value[cormat$value == 10 ] <- NA
cormat$value[cormat$value >= 0.5 ] <- 1
cormat$value[cormat$value <= -0.5 ] <- -1
cormat$value[cormat$value > -0.5 & cormat$value < 0.5 ] <- 0
# Create a ggcorrx
dev.new(width=15, height=15)
gcorx <- ggplot(cormat, aes(Var2, Var1, fill = value, colour=""))+
geom_tile(color = "grey60")+
scale_fill_gradient2(breaks=c(-1,-0.5,0.5,1),low = "red", high = "green", mid =
"yellow", midpoint = 0, limit = c(-1,1), space = "Lab", name="Not ?? OK", na.value="black") +
theme_minimal()+ # minimal theme
theme(axis.text.x = element_text(angle = 50, vjust = 1,
size = 8, hjust = 1))+
theme(axis.text.y = element_text(vjust = 1,
size = 8, hjust = 1))+
scale_y_discrete(position = "right")+
scale_x_discrete()+
coord_fixed()+
ggtitle("MT CARS")+
geom_segment(aes(x=1.5,xend=5.5,y=2.5,yend=2.5), color="black", size=2)+
geom_segment(aes(x=1.5,xend=1.5,y=0.5,yend=2.5), color="black", size=2)+
annotate("text", x=0.7, y=2.5, label= "Part 1", size = 3, color="black",angle = 50,
fontface = "bold")+
annotate("text", x=2, y=4, label="Part 2", size = 3, color="black",angle = 50,
fontface = "bold")
gcorx +
theme(
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.major = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(color="black", size=12, face="bold", hjust = 0.5),
legend.justification = c(1, 0),
legend.position = c(0.3, 0.7),
legend.direction = "horizontal",
legend.title = element_text(size=9, face= "italic"))+
guides(fill = guide_colorbar(barwidth = 8, barheight = 1,title.position = "top",
title.hjust = 0.5))
I can help with the colour scale...
cols <- c("-1" = "red", "0" = "yellow", "1" = "green")
ggplot(cormat, aes(Var2, Var1, fill = value, colour=""))+
geom_tile(aes(fill = factor(value)))+
scale_fill_manual(values = cols)
You can use the function cut to make some new variable, and then change the cols, based on the values from cut, to get 4 instead of 3
https://ggplot2.tidyverse.org/reference/scale_manual.html
As for axis text, you could try turning off the y axis and adding in annotations to the plot instead.
https://ggplot2.tidyverse.org/reference/annotate.html
http://www.sthda.com/english/wiki/ggplot2-axis-ticks-a-guide-to-customize-tick-marks-and-labels
I want to give each facet an alpha code, from A to H since there are eight facets, and draw each code on the top-left of each facet:
ggthemr('dust', layout = 'scientific',
spacing = 1, type = 'inner', line_weight = 0.6,
)
ptitles <- c('A' = "Total mass (g)", 'B' = "Root mass (g)", 'C' = "Stem mass (g)",
'D' = "Leaf mass (g)", 'E' = "Number of nodes",
'F' = "Number of leaves", 'G' = "Total stem length (cm)", 'H' = "RDI")
ggplot(gtr, aes(sediment, value)) +
geom_boxplot(aes(fill = nitrogen)) +
geom_text(aes(label = trait, group = trait)) +
facet_wrap(~trait, scales = "free_y", ncol = 2,
labeller = as_labeller(ptitles),
strip.position = "left"
) +
theme(legend.position = "bottom",
legend.title = element_text(size = 12),
legend.key.size = unit(2, "lines"),
legend.text = element_text(size = 12),
strip.text.x = element_text(size = 12, margin = margin(0, 0, 0, 10)),
strip.text.y = element_text(size = 14),
strip.placement = "outside",
axis.title.y = element_text(size = 14),
axis.title.x = element_text(size = 14),
axis.text.x = element_text(size = 14),
panel.spacing.x = unit(0.5, "lines"),
panel.spacing.y = unit(0.3, "lines"),
aspect.ratio = 2 / 3
) +
xlab("Effects of sediment type and nitrogen deposition") +
ylab(NULL)
I tried to use geom_text():
geom_text(aes(label = trait, group = trait))
(Here the variable trait stores factors from A to H to distinguish each facet)
But it did not work like what I expected:
Is there a simple way to such a thing?
UPDATE:
According to baptiste's answer, I changed my geom_text() code above to below:
geom_text(aes(x = -Inf, y = Inf, label = trait, group = trait),
size = 5,
hjust = -0.5,
vjust = 1.4,
inherit.aes = FALSE)
inherit.aes = FALSE here seems to do nothing, how does this parameter work?.
Now my plot looks good:
library(ggplot2)
d <- data.frame(x=rep(1:3, 4), f=rep(letters[1:4], each=3))
labels <- data.frame(f=letters[1:4], label=LETTERS[1:4])
ggplot(d, aes(x,x)) +
facet_wrap(~f) +
geom_point() +
geom_label(data = labels, aes(label=label),
x = Inf, y = -Inf, hjust=1, vjust=0,
inherit.aes = FALSE)