user10942536
user10942536

Reputation:

Creating a function in R but getting a replacement has length zero error

I tried to create a function f and create the function so when a value x is inserted, it spits out a function f from y.But, when I try to run the code to plot, it gives me an error that says that my y_value has no length.

f <- function(x){
  if (x<0){
   print(y_values<-x*x*x)
  }
  if(x>0 & x<=1){
    print(y_values<-x*x)
  }
  if(x>1){
    print(y_values<-sqrt(x))
  }

}


x_values <- seq(-2, 2, by = 0.1)
y_values <- rep(NA, length(x_values))
for (i in seq_along(x_values)) {
  x <- x_values[i]
  y_values[i] <- f(x)
}

# output
plot(x_values, y_values, type = "l")

Upvotes: 0

Views: 103

Answers (2)

B Williams
B Williams

Reputation: 2050

I would recommend you explore other methods for coding something like this:

here is one option that doesn't use a for loop. If you are simply working on using for loops then the fix Mauritus Evers made should work for you.

library(tidyverse)

data.frame(x_values = seq(-2, 2, by = 0.1)) %>% 
  mutate(y_values = case_when(x_values < 0 ~ x_values^3,
                              x_values>=0 & x_values<=1 ~ x_values^2,
                              x_values>1 ~ sqrt(x_values))) %>% 
  ggplot(aes(x_values, y_values)) + geom_point()

note that I changed your code to produce output when x_value = 0.

Upvotes: 0

Maurits Evers
Maurits Evers

Reputation: 50668

Two issues:

  1. From ?print

    ‘print’ prints its argument and returns it invisibly (via ‘invisible(x)’)

    So all your function f does is print the values to the console (instead of returning them).

  2. As per your definition of f, the function does not know how to deal with x=0; so this will create a problem when you store the output of f(0) later.

We can fix these issues by slightly altering f as

    f <- function(x) {
      y_values <- NA
      if (x<0){
       y_values<-x*x*x
      }
      if(x>0 & x<=1){
        y_values<-x*x
      }
      if(x>1){
        y_values<-sqrt(x)
      }
      return(y_values)
  }

Then

x_values <- seq(-2, 2, by = 0.1)
y_values <- rep(NA, length(x_values))
for (i in seq_along(x_values)) {
  x <- x_values[i]
  y_values[i] <- f(x)
}

plot(x_values, y_values, type = "l")

enter image description here


You could also use Vectorize to obtain a vectorised function f2, which allows you to pass x_values as a vector, thereby avoiding the explicit for loop:

f2 <- Vectorize(f)
x_values <- seq(-2, 2, by = 0.1)
y_values <- f2(x_values)

The resulting plot is the same.

Upvotes: 3

Related Questions