I'm trying to make a plot in ggplot2 of the densities estimated by a model fitted in gamlss.
I performed this using R base, as shown below:
library(gamlss)
library(ggplot2)
data(Orange)
mod.g = gamlss(circumference ~ age,
family=GA, data = Orange)
pred.g <- predict(mod.g, type = "r")
shapex = (mean(pred.g)/sd(pred.g))^2
ratex = mean(pred.g)/sd(pred.g)^2
hist(Orange$circumference, freq = FALSE, breaks = seq(0, 240, 20))
curve(dgamma(x,
shapex,
ratex), add = T,col = "blue",lwd=2)
legend("topright", legend = c("Gamma"), lty = 1, col = "blue")
Result:
However, when I tried to perform this in ggplot2 the lines are not being plotted, see:
ggplot(Orange, aes(x = circumference)) +
geom_histogram(color = "black", fill = "#225EA8", binwidth=30) +
geom_line(aes(shapex, ratex)) +
theme(legend.title = element_text(size = 15),
legend.text = element_text(size = 17),
axis.title = element_text(size = 22),
axis.text.x = element_text(color = "black", hjust=1),
axis.text.y = element_text(color = "black", hjust=1),
axis.text = element_text(size = 15),
strip.text.x = element_text(size = 18))
After_stat is necessary, but doesn't do the entire trick. With curve you are actually plotting a function. You are passing two constants to your geom_line - how are you expecting ggplot2 to know that you want to plot a gamma distribution with those two constants as parameter?
For this, you could use stat_function
ggplot(Orange, aes(x = circumference)) +
geom_histogram(aes(y = after_stat(density)), color = "black", fill = "#225EA8", binwidth=30) +
stat_function(fun = function(x) dgamma(x, shapex, ratex))
Created on 2023-02-15 with reprex v2.0.2
Related
Say, I have a linear mixed-effects model:
## create data
iris$group = c(rep('A', each = 75),
rep('B', each = 75))
iris$id = rep(c(1:10), each = 15)
## assign contrasts
iris$group <- factor(iris$group, levels=c('A', 'B'))
(contrasts(iris$group) <- matrix(dimnames=list(levels(iris$group), c('.sum.group')), c(-0.5, 0.5), nrow=2))
## build the model
LMM = lmer(Sepal.Length ~ 1 +
Sepal.Width +
Petal.Length +
Petal.Width +
group*Petal.Width +
(1|id),
data = iris,
control=lmerControl(optimizer="bobyqa",
optCtrl=list(maxfun=2e5)),
REML = FALSE)
Now, I need to plot the interaction group*Petal.Width from the model using the function ggemmeans. Exactly this function must be used in my case.
The documentation for the function says, it gives a standard ggplot-object as an output. However, I couldn't figure out how to adjust its aesthetics, and it seems that it's not exactly how ggplot would behave. Here is the best that I could achieve:
ggemmeans(LMM, terms = c("Petal.Width", "group")) %>% plot()+
geom_line(aes(linetype=group))+
aes(linetype = group)+
theme(legend.title = element_text(size=30),
legend.position = 'top',
legend.key.size = unit('1.5', 'cm'),
axis.title.y = element_text(size = rel(2), angle = 90),
axis.title.x = element_text(size = rel(2)),
axis.text.x = element_text(size=20),
axis.text.y = element_text(size=20))+
scale_colour_manual(values = c("orangered", "purple"))
Now, how could I at least
Remove the thin dashed line behind the thick dashed one?
Change the color of the confidence intervals to the color of the lines? (now the plot is using standard colors for CIs, whatever color I assign to the lines)
Make sure these CIs reflect 95% CIs and not something else? (e.g., in a similar function plot_model, there's an argument for controlling this)
The fill and color are mapped to a variable called group_col created by ggemmeans, so you can do:
ggemmeans(LMM, terms = c("Petal.Width", "group")) %>%
plot() +
aes(linetype = group_col) +
theme(legend.title = element_text(size=30),
legend.position = 'top',
legend.key.size = unit('1.5', 'cm'),
axis.title.y = element_text(size = rel(2), angle = 90),
axis.title.x = element_text(size = rel(2)),
axis.text.x = element_text(size=20),
axis.text.y = element_text(size=20))+
scale_colour_manual("group", values = c("orangered", "purple")) +
scale_fill_manual("group", values = c("orangered", "purple"),
guide = "legend") +
scale_linetype_manual("group", values = 1:2) +
guides(fill = guide_legend(override.aes =
list(fill = c("orangered", "purple"))))
I would like to plot the congruence effects (incongruent minus congruent) as a violin plot per combination of stimulus age and response type. This is what my code looks like so far. I am not yet satisfied with the representation. How can I change it so that for each of the four conditions (adult frown, adult smile, child frown, child smile) I get the corresponding violin plot horizontally next to each other? Thanks in advance for the help. Attached is the code and an excerpt from the data frame.
violin plot
dataset$congruency_effect <- ifelse(dataset$congruency == "congruent", dataset$avgAmplitude, -dataset$avgAmplitude)
p <- ggplot(dataset, aes(x = stimulusResponse, y = congruency_effect, fill = congruency_effect, group = stimulusAge)) +
geom_violin() +
geom_point(position = position_dodge(width = 0.75), size = 3, stat = "summary", fun.y = "mean") +
scale_fill_manual(values = c("#F8766D", "#00BFC4")) +
ggtitle("Conventional EEG 350-450 ms") +
scale_y_continuous(limits = c(-5, 5)) +
facet_wrap(~stimulusAge, scales = "free_x")
EEG_Conventional450_age_response <- p + theme(
# Set the plot title and axis labels to APA style
plot.title = element_text(face = "bold", size = 16),
axis.title = element_text(face = "bold", size = 14),
# Set the axis tick labels to APA style
axis.text = element_text(size = 12),
# Set the legend title and labels to APA style
legend.title = element_text(face = "bold", size = 14),
legend.text = element_text(size = 12),
# Set the plot and panel backgrounds to white
panel.background = element_rect(fill = "white"),
plot.background = element_rect(fill = "white")
)
EEG_Conventional450_age_response
excerpt data frame
several permutations of arguments in ggplot
This has to do with the grouping aesthetic. Remove it, and your plot works.
library(ggplot2)
set.seed(42)
dataset <- data.frame(stimulusResponse = rep(c("frown", "smile"), each = 20),
congruency_effect = rnorm(40),
stimulusAge = rep(c("baby", "adult"), 20))
## removed group = stimulusAge
ggplot(dataset, aes(x = stimulusResponse, y = congruency_effect)) +
geom_violin() +
geom_point(position = position_dodge(width = 0.75), size = 3, stat = "summary") +
facet_wrap(~stimulusAge, scales = "free_x")
I have made a linear regression figure in R and would like to place some of the statistical output inside of the figure. The stat_cor function allows me to add the R2 and p-value however it does not allow you to add the slope or slope error. I can add the latter two using geom_text however the font is different between stat_cor and geom_text. In my opinion, the stat_cor font looks cleaner, so how can I get the geom_text to look like the stat_cor font?
Example Dataset:
library(ggplot2)
library(ggpubr)
beer <- read.csv("http://users.stat.umn.edu/~helwig/notes/MNbeer.csv")
ggplot(data = beer, aes(x = ABV, y = IBU)) +
stat_smooth(method = 'lm') +
geom_point() +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 14, color = "black"),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = 'black')) +
stat_cor(aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")),
label.x = 4, size = 4)
Here is where I get the slope and its standard error
model <- lm(IBU~ABV, data = beer)
summary(model)
I add the slope ± SE to the plot below using geom_text however their is a difference in the font between the stat_cor output and the geom_text output.
ggplot(data = beer, aes(x = ABV, y = IBU)) +
stat_smooth(method = 'lm') +
geom_point() +
geom_text(x = 4.45 , y = 88,
label = 'Slope = 19.79 ± 2.67',
size = 4.5) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 14, color = "black"),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = 'black')) +
stat_cor(aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")),
label.x = 4, size = 4)
The ideal figure would have the R2, p-value, and slope ± SE all in the same font as stat_cor.
I have produced some nice plots with the plotLearnerPrediction function of the MLR package. I was able to make some adjustments to the returned ggplot (see my code below). But I am not sure how to make the last adjustment. Namely, I want to change the coloring of the data points based on labels (groups in example plot).
My last plot (with black data points)
Another produced plot (overlapping data points)
This is the last version of my code (normally part of a for loop):
plot <- plotLearnerPrediction(learner = learner_name, task = tasks[[i]], cv = 0,
pointsize = 1.5, gridsize = 500) +
ggtitle(trimws(sprintf("Predictions %s %s", meta$name[i], meta$nr[i])),
subtitle = sprintf("DR = %s, ML = %s, CV = LOO, ACC = %.2f", meta$type[i],
toupper(strsplit(learner_name, "classif.")[[1]][2]), acc[[i]])) +
xlab(sprintf("%s 1", lab)) +
ylab(sprintf("%s 2", lab)) +
scale_fill_manual(values = colors) +
theme(plot.title = element_text(size = 18, face = "bold"),
plot.subtitle = element_text(size = 12, face = "bold", colour = "grey40"),
axis.text.x = element_text(vjust = 0.5, hjust = 1),
axis.text = element_text(size = 14, face = "bold"),
axis.title.x = element_text(vjust = 0.5),
axis.title = element_text(size = 16, face = "bold"),
#panel.grid.minor = element_line(colour = "grey80"),
axis.line.x = element_line(color = "black", size = 1),
axis.line.y = element_line(color = "black", size = 1),
panel.grid.major = element_line(colour = "grey80"),
panel.background = element_rect(fill = "white"),
legend.justification = "top",
legend.margin = margin(l = 0),
legend.title = element_blank(),
legend.text = element_text(size = 14))
Below is a part of the source code of the plotLearnerPrediction function. I want to overrule geom_point(colour = "black"). Adding simply geom_point(colour = "pink") to my code will not color data points, but the whole plot. Is there a solution to overrule that code with a vector of colors? Possibly a change in the aes() is also needed to change colors based on groups.
else if (taskdim == 2L) {
p = ggplot(mapping = aes_string(x = x1n, y = x2n))
p = p + geom_tile(data = grid, mapping = aes_string(fill = target))
p = p + scale_fill_gradient2(low = bg.cols[1L], mid = bg.cols[2L],
high = bg.cols[3L], space = "Lab")
p = p + geom_point(data = data, mapping = aes_string(x = x1n,
y = x2n, colour = target), size = pointsize)
p = p + geom_point(data = data, mapping = aes_string(x = x1n,
y = x2n), size = pointsize, colour = "black",
shape = 1)
p = p + scale_colour_gradient2(low = bg.cols[1L],
mid = bg.cols[2L], high = bg.cols[3L], space = "Lab")
p = p + guides(colour = FALSE)
}
You can always hack into gg objects. The following works for ggplot2 2.2.1 and adds a manual alpha value to all geom_point layers.
library(mlr)
library(ggplot2)
g = plotLearnerPrediction(makeLearner("classif.qda"), iris.task)
ids.geom.point = which(sapply(g$layers, function(z) class(z$geom)[[1]]) == "GeomPoint")
for(i in ids.geom.point) {
g$layers[[i]]$aes_params$alpha = 0.1
}
g
The plotLearnerPrediction() function returns the ggplot plot object, which allows for some level of customization without having to modify the source code. In your particular case, you can use scale_fill_manual() to set custom fill colors:
library(mlr)
g = plotLearnerPrediction(makeLearner("classif.randomForest"), iris.task)
g + scale_fill_manual(values = c("yellow", "orange", "red"))
I'm trying to plot a 2D density plot with ggplot, with added marginal histograms. Problem is that the polygon rendering is stupid and needs to be given extra padding to render values outside your axis limits (e.g. in this case I set limits between 0 and 1, because values outside this range have no physical meaning). I still want the density estimate though, because often it's much cleaner than a blocky 2D heatmap.
Is there a way around this problem, besides scrapping ggMarginal entirely and spending another 50 lines of code trying to align histograms?
Unsightly lines:
Now rendering works, but ggMarginal ignores choord_cartesian(), which demolishes the plot:
Data here:
http://pasted.co/b581605a
dataset <- read.csv("~/Desktop/dataset.csv")
library(ggplot2)
library(ggthemes)
library(ggExtra)
plot_center <- ggplot(data = dataset, aes(x = E,
y = S)) +
stat_density2d(aes(fill=..level..),
bins= 8,
geom="polygon",
col = "black",
alpha = 0.5) +
scale_fill_continuous(low = "yellow",
high = "red") +
scale_x_continuous(limits = c(-1,2)) + # Render padding for polygon
scale_y_continuous(limits = c(-1,2)) + #
coord_cartesian(ylim = c(0, 1),
xlim = c(0, 1)) +
theme_tufte(base_size = 15, base_family = "Roboto") +
theme(axis.text = element_text(color = "black"),
panel.border = element_rect(colour = "black", fill=NA, size=1),
legend.text = element_text(size = 12, family = "Roboto"),
legend.title = element_blank(),
legend.position = "none")
ggMarginal(plot_center,
type = "histogram",
col = "black",
fill = "orange",
margins = "both")
You can solve this problem by using xlim() and ylim() instead of coord_cartesian.
dataset <- read.csv("~/Desktop/dataset.csv")
library(ggplot2)
library(ggthemes)
library(ggExtra)
plot_center <- ggplot(data = dataset, aes(x = E,
y = S)) +
stat_density2d(aes(fill=..level..),
bins= 8,
geom="polygon",
col = "black",
alpha = 0.5) +
scale_fill_continuous(low = "yellow",
high = "red") +
scale_x_continuous(limits = c(-1,2)) + # Render padding for polygon
scale_y_continuous(limits = c(-1,2)) + #
xlim(c(0,1)) +
ylim(c(0,1)) +
theme_tufte(base_size = 15, base_family = "Roboto") +
theme(axis.text = element_text(color = "black"),
panel.border = element_rect(colour = "black", fill=NA, size=1),
legend.text = element_text(size = 12, family = "Roboto"),
legend.title = element_blank(),
legend.position = "none")
ggMarginal(plot_center,
type = "histogram",
col = "black",
fill = "orange",
margins = "both")