rplot

Can someone explain strange behavior trying to plot a non-differentiable function?


I have some data that I am using to generate a non-differentiable function and trying to plot it in R and I am observing unexpected behavior: namely, the output of the function during plotting seems to be different than if R calculates the value of the function.

Creating the data

v1 <- c(3.323,4.0034,4.6584,5.2826)
v2 <- c(1200,1300,1400,1500)
data <- cbind(v1, v2)

creating the function

fun <- function(x){
  ans <- NA
  ans[x >= data[1,1] & x <= data[2,1]] <- 100*(x-data[1,1])/(data[2,1]-data[1,1])+data[1,2]
  ans[x >= data[2,1] & x <= data[3,1]] <- 100*(x-data[2,1])/(data[3,1]-data[2,1])+data[2,2]
  ans[x >= data[3,1] & x <= data[4,1]] <- 100*(x-data[3,1])/(data[4,1]-data[3,1])+data[3,2]
  ans
  }

If I evaluate the function at various points I get what I expect

> fun(4.3309)
[1] 1350
> fun(4.0034)
[1] 1300

etc...

If I try to plot the function

plot(fun, type = 'l', xlim = c(3.323,5.2826))

I get warning messages

1: In ans[x >= data[1, 1] & x <= data[2, 1]] <- 100 * (x - data[1, : number of items to replace is not a multiple of replacement length
2: In ans[x >= data[2, 1] & x <= data[3, 1]] <- 100 * (x - data[2, : number of items to replace is not a multiple of replacement length
3: In ans[x >= data[3, 1] & x <= data[4, 1]] <- 100 * (x - data[3, : number of items to replace is not a multiple of replacement length

and a plot that does not match if I just evaluate the function after the first non-differentiation point (if that is the right term)

plot


Solution

  • Your warning comes from below, for example

    ans[x >= data[1,1] & x <= data[2,1]] <- 100*(x-data[1,1])/(data[2,1]-data[1,1])+data[1,2]
    

    where the length of ans[x >= data[1,1] & x <= data[2,1]] is shorter than x, while on the right-hand-side term, 100*(x-data[1,1])/(data[2,1]-data[1,1])+data[1,2] is of the same length of x


    You can try either of the following options

    fun <- function(x) {
        ans <- NA
        msk1 <- x >= data[1, 1] & x <= data[2, 1]
        ans[msk1] <- 100 * (x[msk1] - data[1, 1]) / (data[2, 1] - data[1, 1]) + data[1, 2]
        msk2 <- x >= data[2, 1] & x <= data[3, 1]
        ans[msk2] <- 100 * (x[msk2] - data[2, 1]) / (data[3, 1] - data[2, 1]) + data[2, 2]
        msk3 <- x >= data[3, 1] & x <= data[4, 1]
        ans[msk3] <- 100 * (x[msk3] - data[3, 1]) / (data[4, 1] - data[3, 1]) + data[3, 2]
        ans
    }
    

    or

    fun <- Vectorize(function(x) {
        ans <- NA
        ans[x >= data[1, 1] & x <= data[2, 1]] <- 100 * (x - data[1, 1]) / (data[2, 1] - data[1, 1]) + data[1, 2]
        ans[x >= data[2, 1] & x <= data[3, 1]] <- 100 * (x - data[2, 1]) / (data[3, 1] - data[2, 1]) + data[2, 2]
        ans[x >= data[3, 1] & x <= data[4, 1]] <- 100 * (x - data[3, 1]) / (data[4, 1] - data[3, 1]) + data[3, 2]
        ans
    })
    

    and I believe the warning would be resolved.