Hong Ooi
Hong Ooi

Reputation: 57686

Using approxfun in a package

The help for approx and approxfun includes the following warning:

Warning

The value returned by approxfun contains references to the code in the current version of R: it is not intended to be saved and loaded into a different R session. This is safer for R >= 3.0.0.

I'm not entirely sure what that means, especially the last part about being "safer for R >= 3.0.0". I've written some code that includes a function created with approxfun. Is it safe to now put that code into a package? I've tested it and it seems to work, but I don't know if I can rely on this or not.

This is with R 3.1.1 on Windows 7 64-bit.

The exact code is like this. I have some data on function values, and I want to approximate the underlying function (which I don't have the source code for).

.table <- read.table(text="x y
10.0    150
37.8    147
65.6    145
93.3    142", header=TRUE) # plus several more lines in the original 

# this function is to be exported in the package
f <- with(.table, approxfun(x, y))




EDIT: thanks to @MrFlick for pointing out that the resulting function calls .approxfun which is an unexported function in the stats package. So it's possible that a future version of R might omit this function, although this is probably unlikely, at least in the short term. There is another issue though. I had a closer look at the source for approxfun, and it ends with the following lines:

    ....
    x <- as.double(x)
    y <- as.double(y)
    .Call(C_ApproxTest, x, y, method, f)
    function(v) .approxfun(x, y, v, method, yleft, yright, f)
}

And .approxfun is just:

function (x, y, v, method, yleft, yright, f) 
.Call(C_Approx, x, y, v, method, yleft, yright, f)

It looks like approxfun calls compiled C code to initialise some data, and .approxfun then uses that data. If I call approxfun in my packaged code, can I still depend on that initial C call happening?

Upvotes: 1

Views: 1132

Answers (2)

Richie Cotton
Richie Cotton

Reputation: 121067

Here's an example adapted from example(approxfun).

x <- 1:10
y <- rnorm(10)
f <- approxfun(x, y)

f is a function that approximates the x-y curve at some new points.

set.seed(19790801)
f(runif(10, 1, 10))
##  [1] -0.75163251 -0.75549423 -0.08916802 -0.14773144  0.55004544 -1.04215783 -0.24202646 -0.24400353 -0.16274046 -0.66116177

To do this, it needs to store a copy of x and y somewhere. You can see them using:

environment(f)$x
## [1]  1  2  3  4  5  6  7  8  9 10
environment(f)$y
## [1] -0.2841479  1.0499758 -0.2363440  0.0399924 -0.2607020  0.5553470 -1.5858871 -0.8552268  0.2645726 -1.1651585

So does this work if you save f and load it into a different session?

saveRDS(f, "f.rds")

# Start a new R session now
f <- readRDS("f.rds")

Do we get the same answer in the new session when calling f, even if x and y are defined differently?

x <- 99:90
y <- rlnorm(10)
set.seed(19790801)
f(runif(10, 1, 10))
##  [1] -0.75163251 -0.75549423 -0.08916802 -0.14773144  0.55004544 -1.04215783 -0.24202646 -0.24400353 -0.16274046 -0.66116177

Yes! So it seems safe, at least in this case.


As MrFlick pointed out, the warning is due to f calling stats:::.approxfun, which isn't exported, and therefore could potentially change in future versions of R.

So you are safe copying f between sessions using the same version of R, but not copying it to sessions in potential future versions of R. That is, I'm translating the warning as

Do not use the results of approxfun as a form of permanent data storage.

Upvotes: 1

MrFlick
MrFlick

Reputation: 206197

The warning is more about if you were to use save() and load() on the function returned by approx fun. Using your sample data, if you look at

f
# function (v) 
# .approxfun(x, y, v, method, yleft, yright, f)
# <bytecode: 0x10a20d948>
# <environment: 0x10a20d0d8>

You can see that it's just calling a lower-level (un-exported) function with called .approxfun. This function isn't necessarily meant to be called directory and could change in future R versions. The values that are passed the the function are stored in the environment of the function. Observe:

ls.str(envir=environment(f))
# f :  num 0
# method :  int 1
# x :  num [1:4] 10 37.8 65.6 93.3
# y :  num [1:4] 150 147 145 142
# yleft :  logi NA
# yright :  logi NA

I'm not sure if older versions of R had a problem with storing the enclosure contents or not.

But as long as you are calling approx() and returning a value, you should be fine. The warning just seems to be about preserving the resulting function in an R image data file.

Upvotes: 5

Related Questions