Non-linear regression line and its Computation failed in `stat_smooth()`: argument "p" is missing, with no default error - ggplot2

I have been trying to fit a non-linear regression line into my standard curve. However, I am getting the following error:
The main problem is that with the linear regression line I could use a simple command like:
stat_cor(label.y = c(825),
label.x = c(0.88),
aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")))+
stat_regline_equation(label.x=0.88, label.y=750)+
And the equation for the linear regression line with an a, and b values appear. In this case after using the following:
stat_smooth(method= "nlm",
formula = y~a*x/(b+x),
method.args = list( start = c(a = 3.8, b = 1457.2)),
se=FALSE)+
I am getting the above error.
You may ask where I got the a, and b values? I got them from:
nls(y~a*x/(b+x))
That has shown:
I do not know where I am making mistakes.
This is the entire code for my graph
library(tidyverse)
library(tidyr)
library(dplyr)
library(readr)
library(ggplot2)
library(ggpubr)
ggplot(data = STD, aes(x = Absorbance, y = STD)) +
labs(title = "Quantifying PGD2 in cell culture lysates and its enzymatic reactions ",
caption = "PGD2 ELISA")+
geom_point(colour = "#69b3a2")+
stat_smooth(method= "nlm",
formula = y~a*x/(b+x),
method.args = list( start = c(a = 3.8, b = 1457.2)),
se=FALSE)+
xlab(expression(paste("%B/"~B[0])))+
ylab(expression(paste("Prostaglandin"~ D[2], ~~ " MOX Concentration (pg/ml) ")))+
theme(plot.background = element_rect(fill = "transparent"),
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"))+
theme(legend.spacing.y = unit(0.01, "cm"))+
theme(legend.position = c(0.77, .91),
legend.background = element_rect(colour = NA, fill = NA))+
theme(plot.title = element_text(size = 12, face = "bold.italic"),
plot.caption = element_text(hjust = 0))
That gives the following outcome
And this is DataUsed

So, I think I have found a solution to my problem. I installed the install.packages(drc) in which the four parametric function is included. I set up my data model <- drm(STD ~ Absorbance, fct = LL.4(), data = STD), then plot(model) , and I got
I know it requires some alternations to make it look more professional, but it is just a cosmetic thing that I should be fine to do. Thank you #stefan for your time.

Related

Adding stat = count on top of histogram in ggplot

I've seen some other examples (especially using geom_col() and stat_bin()) to add frequency or count numbers on top of bars. I'm trying to get this to work with geom_histogram() where I have a discrete (string), not continuous, x variable.
library(tidyverse)
d <- cars |>
mutate( discrete_var = factor(speed))
ggplot(d, aes(x = discrete_var)) +
geom_histogram(stat = "count") +
stat_bin(binwidth=1, geom='text', color='white', aes(label=..count..),
position=position_stack(vjust = 0.5)) +
Gives me an error because StatBin requires a continuous x variable. Any quick fix ideas?
The error message gives you the answer: ! StatBin requires a continuous x variable: the x variable is discrete.Perhaps you want stat="count"?
So instead of stat_bin() use stat_count()
And for further reference here is a reproducible example:
library(tidyverse)
d <- cars |>
mutate( discrete_var = factor(speed))
ggplot(data = d,
aes(x = discrete_var)) +
geom_histogram(stat = "count") +
stat_count(binwidth = 1,
geom = 'text',
color = 'white',
aes(label = ..count..),
position = position_stack(vjust = 0.5))

Center the plot title in ggsurvplot

I'm struggling with getting my plot title to the center using ggsurvplot...
I've seen some posts mentioning something like xxxx$plot + theme(....)
but this solution does not seem to work for me.
Here's my code, maybe you can see what I'm missing:
surv_object_CA19.9 <- Surv(time = data_OS$OS_Days / 30, event = data_OS$Status.Death)
CA19.9_surv_fit <- survfit(surv_object_CA19.9 ~ CA19.9.initial_status, data = data_OS)
CA19.9_OS <- ggsurvplot(CA19.9_surv_fit, data = data_OS, pval = TRUE, xlab = "Time [Months]",
ylab = "Overall survival", risk.table = TRUE, legend.title = "",
risk.table.col. = "strata", risk.table.y.text = FALSE, surv.scale = "percent",
break.x.by = 6, xlim = c(0, 60), legend.labs = c("Pathological", "Normal"),
title = "Overall survival for patients with initially pathological or normal CA19-9 values",
CA19.9_OS$plot + theme(plot.title = element_text(hjust = 0.5)))
Thank you for any help! I'm still new to R and not particularly a friend of it yet, so any tips are highly appreciated!
One relatively easy solution is to define your own custom theme based off of the theme that is used in ggsurvplot(). Looking at the documentation for the function shows us that it is applying via ggtheme= the theme theme_survminer(). We can create a custom function that uses %+replace% to overwrite one of the theme elements of interest from theme_survminer():
custom_theme <- function() {
theme_survminer() %+replace%
theme(
plot.title=element_text(hjust=0.5)
)
}
Then, you can use that theme by association with the ggtheme= argument of ggsurvplot():
library(ggplot2)
library(survminer)
require("survival")
fit<- survfit(Surv(time, status) ~ sex, data = lung)
ggsurvplot(fit, data = lung, title='Awesome Plot Title', ggtheme=custom_theme())
#Add parameters to your theme as follows
centr = theme_grey() + theme(plot.title = element_text(hjust = 0.5, face = "bold"))
#Fit the model
fit<- survfit(Surv(time, status) ~ sex, data = lung)
#create survival plot
ggsurvplot(fit, data = lung, title="Your Title Here", ggtheme=centr)

Integrate default color into personalized theme ggplot

I created my own theme and now I also want to standardize the color set that is used. I tried to do this with the list solution, provided in the answer of Viktor in this feed:
Associate a color palette with ggplot2 theme
df <- mtcars
uwvPalet <- c("#0078D2","#003282","#C4D600")
theme_uwv <- function(base_size = 22, base_family = "Verdana"){theme_hc(base_size = base_size, base_family = base_family)%+replace%theme(plot.title = element_text(color = rgb(0, 120, 210)), complete = TRUE)}
theme_uwv2 <- list(theme_uwv, scale_color_manual(values = uwvPalet))
ggplot(df, aes(fill = cyl, x = am, y = mpg)) + geom_bar(position = "dodge", stat="identity") + theme_uwv2()
Unfortunately, I get the error:
Error in theme_uwv2() : could not find function "theme_uwv2"
Anyone know how I can fix this?
The following worked for me. theme_uwv2 needed the value returned from theme_uwv() as a list element, not the function itself. Also, you were making a plot where the fill was the dominant colour variable, so I've substituted scale_color_manual() with scale_fill_manual() for demonstration purposes.
library(ggplot2)
library(ggthemes)
df <- mtcars
uwvPalet <- c("#0078D2","#003282","#C4D600")
theme_uwv <- function(base_size = 22, base_family = "Verdana"){
theme_hc(base_size = base_size, base_family = base_family) %+replace%
theme(plot.title = element_text(color = rgb(0, 120, 210, maxColorValue = 255)),
complete = TRUE)}
theme_uwv2 <- list(theme_uwv(), scale_fill_manual(values = uwvPalet))
ggplot(df, aes(fill = as.factor(cyl), x = am, y = mpg)) +
geom_col(position = "dodge") +
ggtitle("test") +
theme_uwv2

How to extract stat_smooth curve maxima in gpplot panel (facet_grid)?

I have created this plot with 18 grids using facet_grid command and two different fitting equations (for Jan - Apr, and May - Jun). I have two things that I need help with:
(may sound obvious, but) I haven't been able to find on the internet working codes extract a curve maximum for a stat_smooth fit. I'd appreciate if someone could show and explain what the codes mean. This is the closest I could find, but I am not sure what it means:
gb <- ggplot_build(p1)
curve_max <- gb$data[[1]]$x[which(diff(sign(diff(gb$data[[1]]$y)))==-2)+1]
How to add a vertical line to indicate max value on each curve?
Data file (rlc2 <- read_excel)
Plot
plot <- ggplot(rlc2, aes(par, etr, color=month, group=site))+
geom_point()+
stat_smooth(data = subset(rlc2, rlc2$month!="May" & rlc2$month!="Jun"),
method = "glm",
formula = y ~ x + log(x),
se = FALSE,
method.args = list(family = gaussian(link = "log"), start=c(a=0, b=0, c=0)))+
stat_smooth(data = subset(rlc2, rlc2$month=="May" | rlc2$month=="Jun"),
method = "nlsLM",
formula = y ~ M*(1 - exp(-(a*x))),
se = FALSE,
method.args = list(start=c(M=0, a=10)))+
facet_grid(rows = vars(month), cols = vars(site))
plot
field_rlc_plot
Any other advice are also welcome. I am educated as programmer so my codes are probably a bit messy. Thank you for helping.
Try this:
First, fit the data and extract the maximum of the fit.
my.fit <- function(month, site, data) {
fit <- glm(formula = etr ~ par + log(par),
data = data,
family=gaussian(link = "log")
)
#arrange the dersired output in a tibble
tibble(max = max(fit$fitted.values),
site = site,
month = month)
}
#Apply a custom function `my.fit` on each subset of data
#according to month and site using the group_by/nest/map method
# the results are rowbinded and returned in a data.frame
my.max<-
rlc2 %>%
dplyr::group_by(month, site) %>%
tidyr::nest() %>%
purrr::pmap_dfr(my.fit)
Next, join the results back on your data and plot a geom_line
rlc2 %>%
dplyr::left_join(my.max) %>%
ggplot(aes(x = par, y = etr))+
geom_point()+
stat_smooth(data = subset(rlc2, rlc2$month!="May" & rlc2$month!="Jun"),
method = "glm",
formula = y ~ x + log(x),
se = FALSE,
method.args = list(family = gaussian(link = "log"), start=c(a=0, b=0, c=0)))+
stat_smooth(data = subset(rlc2, rlc2$month=="May" | rlc2$month=="Jun"),
method = "nlsLM",
formula = y ~ M*(1 - exp(-(a*x))),
se = FALSE,
method.args = list(start=c(M=0, a=10)))+
geom_line(aes(y=max), col="red")+
facet_grid(rows = vars(month), cols = vars(site))

Is it possible to have 2 legends for variables when one is continuous and the other is discrete?

I checked a few examples online and I am not sure that it can be done because every plot with 2 different variables (continuous and discrete) has one of 2 options:
legend regarding the continuous variable
legend regarding the discrete variable
Just for visualization, I put here an example. Imagine that I want to have a legend for the blue line. Is it possible to do that??
The easiest approach would be to map it to a different aesthetic than you already use:
library(ggplot2)
ggplot(mtcars, aes(x = mpg, y = hp)) +
geom_point(aes(colour = as.factor(gear), size = cyl)) +
geom_smooth(method = "loess", aes(linetype = "fit"))
There area also specialised packages for adding additional colour legends:
library(ggplot2)
library(ggnewscale)
ggplot(mtcars, aes(x = mpg, y = hp)) +
geom_point(aes(colour = as.factor(gear), size = cyl)) +
new_scale_colour() +
geom_smooth(method = "loess", aes(colour = "fit"))
Beware that if you want to tweak colours via a colourscale, you must first add these before calling the new_scale_colour(), i.e.:
ggplot(mtcars, aes(x = mpg, y = hp)) +
geom_point(aes(colour = as.factor(gear), size = cyl)) +
scale_colour_manual(values = c("red", "green", "blue")) +
new_scale_colour() +
geom_smooth(method = "loess", aes(colour = "fit")) +
scale_colour_manual(values = "purple")
EDIT: To adress comment: yes it is possible with a line that is data independent, I was just re-using the data for brevity of example. See below for arbitrary line (also should work with the ggnewscale approach):
ggplot(mtcars, aes(x = mpg, y = hp)) +
geom_point(aes(colour = as.factor(gear), size = cyl)) +
geom_line(data = data.frame(x = 1:30, y = rnorm(10, 200, 10)),
aes(x, y, linetype = "arbitrary line"))