1

I have a function that gives me a single output which is however composed of two elements. Example for it would be:

example <- function(x){
  sin <- sin(x)
  cos <- cos(x)
  output <- cbind(sin, cos)
  return(output)
}

Now my idea is to plot separately sin and cos, each as functions of x. I would like to avoid writing a separate function in this context since the two objects are better to be calculated all at once. If I try :

x_grid = seq(0,1,0,0.05)
plot(x_grid, sapply(x_grid, FUN = example[1]))

I get the following error message :

Error in example[1] : object of type 'closure' is not subsettable

How to proceed then? (notice that I use sapply because I need my function to deal with more than a single value of x in my real case).

0

3 Answers 3

2

If you're looking for a non-base graphics solution:

library(ggplot2)
example3 <- function(x){
  data.frame(
    x = x,
    sin = sin(x),
    cos = cos(x)
  )
}

x_grid=seq(0,1,0.05)
ggplot(data = example3(x_grid),
       aes(x=x)) +
  geom_line(aes(y = sin), color = "blue") +
  geom_line(aes(y = cos), color = "red")

With the output: enter image description here

Sign up to request clarification or add additional context in comments.

Comments

2

Your function is vectorized so you can input a vector and extract each column by example(x_grid)[, "sin"] or example(x_grid)[, "cos"].

example(x_grid)
#                 sin          cos
#   [1,]  0.000000000  1.000000000
#   [2,]  0.049979169  0.998750260
#   [3,]  0.099833417  0.995004165
example(x_grid)[, "sin"]

# [1]  0.000000000  0.049979169  0.099833417  0.149438132  0.198669331
# [6]  0.247403959  0.295520207  0.342897807  0.389418342  0.434965534

Note: In this case, sapply is not recommended because the function itself has been vectorized. sapply will make it inefficient. Here is an illustration by benchmark:

library(microbenchmark)
bm <- microbenchmark(
  basic = example(x_grid)[, 1],
  sapply = sapply(x_grid, function(x) example(x)[1]),
  times = 1000L
)
ggplot2::autoplot(bm)


If you want to plot both the two functions, matplot() can plot each column of one matrix.

x_grid <- seq(0, 10, 0.05)
matplot(x_grid, example(x_grid), type = "l")

Comments

1

Appears to be an extra parameter to seq

x_grid <- seq(0, 1, 0.05)

Slight modification to pass variable to function and then subset

plot(x_grid, sapply(x_grid, function(x) example(x)[1]))

Another approach for function which uses a list and then the function can be subset by name

example2 <- function(x) {
  within(list(), {
    sin <- sin(x)
    cos <- cos(x)
  })
}

plot(x_grid, sapply(x_grid, function(x) example2(x)$sin))

Unless the example is simplified, the following works without sapply

plot(x_grid, example2(x_grid)$sin)

Plotting both results

lapply(example2(x_grid), plot, x_grid)

1 Comment

your second line did the job. Simple and effective!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.