Adjusting facet order and legend labels when using plot_model function of sjplot - r

I have successfully used the plot_model function of sjplot to plot a multinomial logistic regression model. The regression contains an outcome (Info Sought, with 3 levels) and 2 continuous predictors (DSA, ASA). I have also changed the values of ASA in the plot_model so as to plot predicted effect outcomes based on the ASA mean value and SDs:
plot1 <- plot_model(multinomialmodel , type = "pred", terms = c("DSA", "ASA[meansd]")
I have two customization questions:
1) Facet Order: The facet order is based on the default alphabetical order of the outcome levels ("Expand" then "First Pic" then "Multiple Pics"). Is there a means by which to adjust this? I tried resorting the levels with factor() (as exampled here with ggplot2) prior to running and plotting the model, but this did not cause any changes in the resulting facet order. Perhaps instead something through ggplot2, as exampled in the first solution provided here?
2) Legend Labels: The legend currently labels the plotted lines with the -1 SD, mean, and +1 SD values for ASA; is there a way to adjust these labels to instead simply say "-1 SD", "mean", and "+1 SD" instead of the raw values?
Thanks!

First I replicate your plot using your supplied data:
library(dplyr)
library(readr)
library(nnet)
library(sjPlot)
"ASA,DSA,Info_Sought
-0.108555801,0.659899854,First Pic
0.671946671,1.481880373,First Pic
2.184170211,-0.801398848,First Pic
-0.547588442,1.116555698,First Pic
-1.27930951,-0.299077419,First Pic
0.037788412,1.527545958,First Pic
-0.74271406,-0.755733264,Multiple Pics
1.20854212,-1.166723523,Multiple Pics
0.769509479,-0.390408588,Multiple Pics
-0.450025633,-1.02972677,Multiple Pics
0.769509479,0.614234269,Multiple Pics
0.281695434,0.705565438,Multiple Pics
-0.352462824,-0.299077419,Expand
0.671946671,1.481880373,Expand
2.184170211,-0.801398848,Expand
-0.547588442,1.116555698,Expand
-0.157337206,1.070890114,Expand
-1.27930951,-0.299077419,Expand" %>%
read_csv() -> d
multinomialmodel <- multinom(Info_Sought ~ ASA + DSA, data = d)
p1 <- plot_model(multinomialmodel ,
type = "pred",
terms = c("DSA", "ASA[meansd]"))
p1
Your attempt to re-factor did not work because sjPlot::plot_model() does not pay heed. One way to tackle reordering the facets is to produce an initial plot as above and replace the faceting variable in the data with a factor version containing your desired order like so:
p2 <- p1
p2$data$response.level <- factor(p2$data$response.level,
levels = c("Multiple Pics", "First Pic", "Expand"))
p2
Finally, to tackle the legend labeling issue, we can just replace the color scale with one containing your desired labels:
p2 +
scale_color_discrete(labels = c("-1 SD", "mean", "+1 SD"))

Just following up on #the-mad-statter's answer, I wanted to add a note on how to change the legend title and labels when you're working with a black-and-white graph where the lines differ by linetype (i.e. using sjplot's colors = "bw" argument).
p1 <- plot_model(multinomialmodel ,
type = "pred",
terms = c("DSA", "ASA[meansd]"),
colors = "bw)
As the lines are all black, if you would like to change the axis title and labels, you need to use the scale_linetype_manual() function instead of scale_color_discrete(), like this:
p1 + scale_linetype_manual(name = "ASA values",
values = c("dashed", "solid", "dotted"),
labels = c("Low (-1 SD)", "Medium (mean)", "High (+1 SD)"))
The resulting graph with look like this:
Note that I also took this opportunity to change how linetypes are assigned to values, making the line corresponding to the mean of ASA solid.

Related

Select data and name when pointing it chart with ggplotly

I did everything in ggplot, and it was everything working well. Now I need it to show data when I point a datapoint. In this example, the model (to identify point), and the disp and wt ( data in axis).
For this I added the shape (same shape, I do not actually want different shapes) to model data. and asked ggplot not to show shape in legend. Then I convert to plotly. I succeeded in showing the data when I point the circles, but now I am having problems with the legend showing colors and shapes separated with a comma...
I did not wanted to make it again from scrach in plotly as I have no experience in plotly, and this is part of a much larger shiny project, where the chart adjust automatically the axis scales and adds trend lines the the chart among other things (I did not include for simplicity) that I do not know how to do it in plotly.
Many thanks in advance. I have tried a million ways for a couple of days now, and did not succeed.
# choose mtcars data and add rowname as column as I want to link it to shapes in ggplot
data1 <- mtcars
data1$model <- rownames(mtcars)
# I turn cyl data to character as when charting it showed (Error: Continuous value supplied to discrete scale)
data1$cyl <- as.character(data1$cyl)
# linking colors with cylinders and shapes with models
ccolor <- c("#E57373","purple","green")
cylin <- c(6,4,8)
# I actually do not want shapes to be different, only want to show data of model when I point the data point.
models <- data1$model
sshapes <- rep(16,length(models))
# I am going to chart, do not want legend to show shape
graff <- ggplot(data1,aes(x=disp, y=wt,shape=model,col=cyl)) +
geom_point(size = 1) +
ylab ("eje y") + xlab('eje x') +
scale_color_manual(values= ccolor, breaks= cylin)+
scale_shape_manual(values = sshapes, breaks = models)+
guides(shape='none') # do not want shapes to show in legend
graff
chart is fine, but when converting to ggplotly, I am having trouble with the legend
# chart is fine, but when converting to ggplotly, I am having trouble with the legend
graffPP <- ggplotly(graff)
graffPP
legend is not the same as it was in ggplot
I succeeded in showing the model and data from axis when I point a datapoint in the chart... but now I am having problems with the legend....
To the best of my knowledge there is no easy out-of-the box solution to achieve your desired result.
Using pure plotly you could achieve your result by assigning legendgroups which TBMK is not available using ggplotly. However, you could assign the legend groups manually by manipulating the plotly object returned by ggplotly.
Adapting my answer on this post to your case you could achieve your desired result like so:
library(plotly)
p <- ggplot(data1, aes(x = disp, y = wt, shape = model, col = cyl)) +
geom_point(size = 1) +
ylab("eje y") +
xlab("eje x") +
scale_color_manual(values = ccolor, breaks = cylin) +
scale_shape_manual(values = sshapes, breaks = models) +
guides(shape = "none")
gp <- ggplotly(p = p)
# Get the names of the legend entries
df <- data.frame(id = seq_along(gp$x$data), legend_entries = unlist(lapply(gp$x$data, `[[`, "name")))
# Extract the group identifier, i.e. the number of cylinders from the legend entries
df$legend_group <- gsub("^\\((\\d+).*?\\)", "\\1", df$legend_entries)
# Add an indicator for the first entry per group
df$is_first <- !duplicated(df$legend_group)
for (i in df$id) {
# Is the layer the first entry of the group?
is_first <- df$is_first[[i]]
# Assign the group identifier to the name and legendgroup arguments
gp$x$data[[i]]$name <- df$legend_group[[i]]
gp$x$data[[i]]$legendgroup <- gp$x$data[[i]]$name
# Show the legend only for the first layer of the group
if (!is_first) gp$x$data[[i]]$showlegend <- FALSE
}
gp

how to display corresponding legend when using scale_shape_identity()?

Hello I Have a plot showing a PCA reuslt, the issue is that I want to show how the points behave in the plot accoriding to two variables, let's say sample date and depth of sampling:
I use autoplot for this porpuse:
autoplot(PCA_results, data = data1, colour = 'sample_date' ,
shape = 'depth_m', main = "PCA for samples") + scale_shape_identity()
I had to use scale_shape_identity() due to the fact that the "depth_m" variable have two continuous values (5 meters and 20 meters) and was not acepted without scale_shape_identity()
the resulting plot is the following one:
So in addition to showing sample_date variable in the legend I want to display the depth one too, how can I do this ?
The description of the help menu of scale_shape_identity() appoints that "These scales will not produce a legend unless you also supply the breaks, labels, and type of guide you want." But I'm not sure how to provide the labels, breaks and type of guide.

How does one control the appearance (e.g. line size, line type, colour) of mqgam plots produced using plot.mgamViz from the "mgcViz" package?

I am using quantile regression in R with the qgam package and visualising them using the mgcViz package, but I am struggling to understand how to control the appearance of the plots. The package effectively turns gams (in my case mqgams) into ggplots.
Simple reprex:
egfit <- mqgam(data = iris,
Sepal.Length ~ s(Petal.Length),
qu = c(0.25,0.5,0.75))
plot.mgamViz(getViz(egfit))
I am able to control things that can be added, for example the axis labels and theme of the plot, but I'm struggling to effect things that would normally be addressed in the aes() or geom_x() functions.
How would I control the thickness of the line? If this were a normal geom_smooth() or geom_line() I'd simply put size = 1 inside of the geoms, but I cannot see how I'd do so here.
How can I control the linetype of these lines? The "id" is continuous and one cannot supply a linetype to a continuous scale. If this were a nomral plot I would convert "id" to a character, but I can't see a way of doing so with the plot.mgamViz function.
How can I supply a new colour scale? It seems as though if I provide it with a new colour scale it invents new ID values to put on the legend that don't correlate to the actual "id" values, e.g.
plot.mgamViz(getViz(egfit)) + scale_colour_viridis_c()
I fully expect this to be relatively simple and I'm missing something obvious, and imagine the answer to all three of these subquestions are very similar to one another. Thanks in advance.
You need to extract your ggplot element using this:
p1 <- plot.mgamViz(getViz(egfit))
p <- p1$plots [[1]]$ggObj
Then, id should be as.factor:
p$data$id <- as.factor(p$data$id)
Now you can play with ggplot elements as you prefer:
library(mgcViz)
egfit <- mqgam(data = iris,
Sepal.Length ~ s(Petal.Length),
qu = c(0.25,0.5,0.75))
p1 <- plot.mgamViz(getViz(egfit))
# Taking gg infos and convert id to factor
p <- p1$plots [[1]]$ggObj
p$data$id <- as.factor(p$data$id)
# Changing ggplot attributes
p <- p +
geom_line(linetype = 3, size = 1)+
scale_color_brewer(palette = "Set1")+
labs(x="Petal Length", y="s(Petal Length)", color = "My ID labels:")+
theme_classic(14)+
theme(legend.position = "bottom")
p
Here the generated plot:
Hope it is useful!

Differentiating each Line with different type in `ggsurv` plots (or in `plot`)

I am using Rstudio. I am using ggsurv function from GGally package for drawing Kaplan-Meier curves for my data (for survival analysis), from tutorial here. I am using it instead of plot because ggsurv takes care of legends by itself.
As shown on the link, multiple curves are differentiated by color. I want to differentiate based on linetype. The tutorial does not seem to have any option for that. Following is my command:
surv1 <- survfit(Surv(DaysOfTreatment,Survived)~AgeOnFirstContactGroup)
print(ggsurv(surv1, lty.est = 3)+ ylim(0, 1))
lty.est=3(or 2) gives same dashed lines for all the lines. I want differently dashed line for each line. Using lty=type gives error:object 'type' not found. And lty=type would work in ggplot but ggplot does not directly deal with survfit plots.
Please show me how to differentiate curves by linetype in either ggsurv or simple plot (although I would prefer ggsurv because it takes care of legends)
From the documentation for ggsurv
lty.est: linetype of the survival curve(s). Vector length should be
either 1 or equal to the number of strata.
So, to get a different line type for each stratum, set lty.est equal to a vector of the same length as the number of lines you are plotting, with each value corresponding to a different line type.
For example, using the lung data from the survival package
library(GGally)
library(survival)
data(lung)
surv1 <- survfit(Surv(time,status) ~ sex, data = lung)
ggsurv(surv1, lty.est=c(1,2), surv.col = 1)
Gives the following plot
You can add ggplot themes or other ggplot elements to the plot too. For example, we can improve the appearance using the cowplot theme as follows
library(ggplot2)
library(cowplot)
ggsurv(surv1, lty.est=c(1,2), surv.col = 1) + theme_cowplot()
If you need to change the legend labels after differentiating by linetype, then you can do it this way
ggsurv(surv1, lty.est=c(1,2), surv.col = 1) +
guides(colour = FALSE) +
scale_linetype_discrete(name = 'Sex', breaks = c(1,2), labels = c('Male', 'Female'))

ggplot2 legend for abline and stat_smooth

I have some problems with ggplot legends, here is my first code with only the legend for corrGenes, which is fine.
gene1=c(1.041,0.699,0.602,0.602,2.585,0.602,1.000,0.602,1.230,1.176,0.699,0.477,1.322)
BIME = c(0.477,0.477,0.301,0.477,2.398,0.301,0.602,0.301,0.602,0.699,0.602,0.477,1.176)
corrGenes=c(0.922,0.982,0.934,0.917,0.993,0.697,0.000,0.440,0.859,0.788,0.912,0.687,0.894)
DF=data.frame(gene1,BIME,corrGenes)
plot= ggplot(data=DF,aes(x=gene1,y=BIME))+
geom_point(aes(colour=corrGenes),size=5)+
ylab("BIME normalized counts (log10(RPKM))")+
xlab("gene1 normalized counts (log10(RPKM))")
When I add abline and smooth, I get the correct plot with :
plot= ggplot(data=DF,aes(x=gene1,y=BIME))+
geom_point(aes(colour=corrGenes),size=5)+
geom_abline(intercept=0, slope=1)+
stat_smooth(method = "lm",se=FALSE)+
ylab("BIME normalized counts (log10(RPKM))")+
xlab("gene1 normalized counts (log10(RPKM))")
but no way to get the legend for them, I tried and many other combinations:
plot= ggplot(data=DF,aes(x=gene1,y=BIME))+
geom_point(aes(colour=corrGenes),size=5)+
geom_abline(aes(colour="best"),intercept=0, slope=1)+
stat_smooth(aes(colour="data"),method = "lm",se=FALSE)+
scale_colour_manual(name="Fit", values=c("data"="blue", "best"="black"))+
ylab("BIME normalized counts (log10(RPKM))")+
xlab("gene1 normalized counts (log10(RPKM))")
If anyone has an idea to solve this tiny but very annoying problem, it would be very helpfull!
Finally, I found anther way using a trick. First, I've computed the linear regression and convert the results to a data frame which I add my best fit (Intercept = 0 and slope =1), then I added a column for type of data (data or best).
modele = lm(BIME ~ gene1, data=DF)
coefs = data.frame(intercept=coef(modele)[1],slope=coef(modele)[2])
coefs= rbind(coefs,list(0,1))
regression=as.factor(c('data','best'))
coefs=cbind(coefs,regression)
then I plotted it with a unique geom_abline command and moving the DF from ggplot() to geom_point() and used the linetype parameter to differenciate the two lines :
plot = ggplot()+
geom_point(data=pointSameStrandDF,aes(x=gene1,y=BIME,colour=corrGenes),size=5)+
geom_abline(data=coefs, aes(intercept=intercept,slope=slope,linetype=regression), show_guide=TRUE)+
ylab("BIME normalized counts (log10(RPKM))")+
xlab("gene1 normalized counts (log10(RPKM))")
There is maybe a way to use colors for those 2 lines, but I can't find out how?
Thanks for your help guys!
The show_guide=TRUE argument should display the legends for both geom_abline and stat_smooth. Try running the below code.
plot= ggplot(data=DF,aes(x=gene1,y=BIME))+
geom_point(aes(colour=corrGenes),size=5)+
geom_abline(aes(colour="best"),intercept=0, slope=1, show_guide=TRUE)+
stat_smooth(aes(colour="data"),method = "lm",se=FALSE, show_guide=TRUE)+
scale_colour_manual(name="Fit", values=c("data"="blue", "best"="black"))+
ylab("BIME normalized counts (log10(RPKM))")+
xlab("gene1 normalized counts (log10(RPKM))")
Not sure if this is the best solution, but I was able to tell ggplot to have two scales, one for the colours (your points), the other one for the fill colour. Which fill colour you are probably asking? The one I added in the aes for the two lines:
plot = ggplot(data=DF,aes(x=gene1,y=BIME)) +
geom_point(size=5, aes(colour=corrGenes)) +
geom_abline(aes(fill="black"),intercept=0, slope=1) +
stat_smooth(aes(fill="blue"), method = "lm",se=FALSE) +
scale_fill_manual(name='My Lines', values=c("black", "blue"))+
ylab("BIME normalized counts (log10(RPKM))")+
xlab("gene1 normalized counts (log10(RPKM))")

Resources