How to correctly pass args to ggplot stat_function - r

I have tried to fix this problem a number of ways, but I am new to R, so I don't know the tips and tricks. I am trying to graph a polynomial function using code for a quadratic function, provided by my teacher, however, I keep running into the "unused arguments error". the issue is that I have given three arguments, which is what the function expects. this is the code I entered:
> quadratic <- function(x, u.values){
+ X <- cbind(1, x, x^2)
+ return(X %*% u.values)
+ }
> dev.new()
> ggplot() +
+ geom_point(aes(x = t,y = y),data= GData)+
+ stat_function(fun=quadratic(args=c(1.9604816, -0.1201548, -4.9768049)))
Error in quadratic(args = c(1.9604816, -0.1201548, -4.9768049)) :
unused argument(s) (args = c(1.9604816, -0.1201548, -4.9768049))

As you've defined it, quadratic doesn't have an args parameter. That's what's causing your error.
I'm guessing -- but I can't test, since your example isn't reproducible -- that you should change args in your stat_function call to something like args = list(u.values = c(1.9604816, -0.1201548, -4.9768049)).
Edit:
To clarify, args parameter of stat_function takes additional arguments to the function you specify (quadratic in this case) as a list. What you're doing is passing a named argument args to quadratic, when you want to be passing a named argument args to stat_function.
Here is a reproducible example that works:
g <- data.frame(t = seq(0.1, 1, by = 0.1), y = seq(2.1, 3, by = 0.1))
quadratic <- function(x, u.values){
X <- cbind(1, x, x^2)
return(X %*% u.values)
}
ggplot(data = g, aes(x = t, y = y)) +
geom_point() +
stat_function(fun = quadratic,
args = list(u.values = c(1.9604816, -0.1201548, -4.9768049)))
Obviously this data has nothing to do with yours, but the quadratic function is applied correctly to the data and the results are plotted.

Related

Capturing warning message into a variable in RR

I have a function draw_plot() that takes in a data frame and other parameters(through the ellipsis) and simply returns a line plot.
draw_plot <- function(data, ...){
plot <- ggplot(data = data, mapping = aes(x = x, y = y))
plot <- plot + do.call("geom_line", c(list(...)))
return(plot)}
data <- tibble::tibble(x = c(1,2,3,4,5,6), y = c(5,6,7,8,9,10))
draw_plot(data, test = 2, wrong = "")
If I call the function as above, with parameters with key values which the geom_line() function doesn't recognize, it returns a warning saying 'Ignoring unknown parameters: test, wrong'.
I am hoping to improve the function to facilitate more parameters, and other ggplot geoms. (ex: draw_plot(data, stat, ...)) The stat parameter will not be valid for geom_line(). Therefore I want to capture the original warning message and append 'stat' to it. ex: 'Ignoring unknown parameters: test, wrong, stat'
To do this, is there any way that I can capture this particular warning message into a variable? p.s. I am trying to stick to base R to do this.
Here is how you can capture the warning message -
draw_plot <- function(data, ...){
plot <- ggplot(data = data, mapping = aes(x = x, y = y))
plot <- tryCatch(plot + do.call("geom_line", c(list(...))),
warning = function(w) {
if(grepl('Ignoring unknown parameters', w$message))
wmsg <<- as.character(w$message)
return(NULL)
})
if(exists('wmsg')) print(wmsg)
return(plot)
}
draw_plot(data, test = 2, wrong = "")
draw_plot(data)

Adding various functions to the same plot with a loop ggplot2

I have the following equation: y = 1 - cx, where c is a real number.
I'm trying to make something where I can pick the range of values for c and plot all the graphs of every function with the corresponding c.
Here's what I got as of now:
p <- ggplot(data = data.frame(x = 0), mapping = aes(x = x))
statfun1 <- c()
for (i in 1:3){
c <- i
fun1.i <- function(x){1 - c*x}
fun1.i.plot <- stat_function(fun = fun1.i, color="red")
statfun1 <- statfun1 + fun1.i.plot
}
p + statfun1 + xlim(-5, 5)
The p is basically what you need in ggplot2 to plot a function, then I go over in this case the values 1, 2 and 3 for c and I try to add them all at the end but this does not seem to work. Anyone maybe can help me out or put me on the right track?
Define your function
fun1.i <- function(x, c){1 - c*x}
Now from ?`+.gg`
You can add any of the following types of objects:
...
You can also supply a list, in which case each element of the list will be added in turn.
So you might use lapply
p + xlim(-5, 5) + lapply(1:3, function(c) {
stat_function(fun = fun1.i, args = list(c = c), geom = "line", color="red")
})
Result

Receiving errors when trying to use stat_function in ggplot

So my example data are:
x <- runif(1000, min = 0, max = 5)
y <- (2 / pi) * atan(x)
z <- floor(x)
df <- data.frame(x, y, z)
I draw boxplots of x, binned by z:
library(ggplot2)
g <- ggplot(df, aes(x = x, y = y, group = z)) +
geom_boxplot()
g
But the thing is, in my real-life data, I'm not completely sure that the y-values follow (2 / pi) * atan(x). There's a random element there. So, how do I draw the function on top of my graph to see for myself? As per the ggplot2 documentation, I tried...
g + stat_function(fun = (2 / pi) * atan(x), colour = "red")
...but am receiving the error Warning message:
Computation failed in 'stat_function()':
'what' must be a function or character string.
The error is saying:
'what' must be a function or character string
so it is asking you simply define your function.
You need to define your function suuch as func
func<-function(x){ (2 / pi) * atan(x)}
and then call it in ggplot
library(ggplot2)
g <- ggplot(df, aes(x = x, y = y, group = z)) +
geom_boxplot()
g+stat_function(fun = func, colour = "red")
Here is the result
the parameter fun must be a function
g + stat_function(fun = function(x){(2 / pi) * atan(x)}, colour = "red")
I could solve your problem by simply defining a new function and the pass it to as the argument of stat_function
Here it is
myfun <- function(x){(2 / pi) * atan(x)}
and then
g + stat_function(fun = myfun colour = "red")
would do it

Plotting multiple variable function in R

I'm needing help with the following question:
Consider the following R function, named negloglike that has two input arguments: lam and x, in that order.
Use this function to produce a plot of the log-likelihood function over a range of values λ ∈ (0, 2).
negloglike <- function(lam, x) {
l = -sum(log(dexp(x, lam)))
return(l)
}
Can anyone please help? Is it possible to do something like this with ggplot? I've been trying to do it with a set value of lam (like 0.2 here for example) using stat_function:
ggplot(data = data.frame(x = 0), mapping = aes(x = x)) +
stat_function(fun = negloglike, args = list(lam = 0.2)) +
xlim(0,10)
but the plot always returns a horizontal line at some y-value instead of returning a curve.
Should I be possibly using a different geom? Or even a different package altogether?
Much appreciated!
The trick is to Vectorize the function over the argument of interest.
Thanks for the tip go to the most voted answer to this question. It uses base graphics only, so here is a ggplot2 equivalent.
First I will define the negative log-likelihood using function dexp
library(ggplot2)
negloglike <- function(lam, x) {negloglike <- function(lam, x) {
l = -sum(dexp(x, lam, log = TRUE))
return(l)
}
nllv <- Vectorize(negloglike, "lam")
But it's better to use the analytic form, which is easy to establish by hand.
negloglike2 <- function(lam, x) {
l = lam*sum(x) - length(x)*log(lam)
return(l)
}
nllv2 <- Vectorize(negloglike2, "lam")
ggplot(data = data.frame(lam = seq(0, 2, by = 0.2)), mapping = aes(x = lam)) +
stat_function(fun = nllv2, args = list(x = 0:10))
Both nllv and nllv2 give the same graph.

How to map stat_function aesthetics to data in ggplot2?

I want to add a stat_function layer to a plot with an aesthetic mapped to the state of some variable that identifies a set of parameters. I have manually created the two stat_function lines in the minimal working example below. That's generally what the result should look like.
p <- ggplot(data.frame(x = -1:1), aes(x = x))
p + stat_function(fun = function (x) 0 + 1 * x, linetype = 'dotted') +
stat_function(fun = function (x) 0.5 + -1 * x, linetype = 'solid')
My best guess at how to accomplish this is
params <- data.frame(
type = c('true', 'estimate'),
b = c(0, 0.5),
m = c(1, -1),
x = 0
)
linear_function <- function (x, b, m) b + m * x
p + stat_function(data = params,
aes(linetype = type, x = x),
fun = linear_function,
args = list(b = b, m = m))
This form works if I use constants like args = list(b = 0, m = 1), but when I try to get the values for the parameters out of the params data frame it's unable to find those columns. Why is this not working like I expect and what's a solution?
Unfortunately, nothing positive to add here; the fact stands: stat_function does not support this functionality.
The alternative is to either use for loops to make layers, as demonstrated in this question, or generate the grid data yourself, which is what was suggested as a closing comment to a feature request discussion about adding this functionality.

Resources