Home > OS >  How can a make the sum of two step functions (R-stepfun) of class "stepfun"?
How can a make the sum of two step functions (R-stepfun) of class "stepfun"?

Time:10-28

From the example here I tried to make the sum as class "stepfun". I thought, as.stepfun is the right choice, but my ideas don't work. What is wrong?

y1 <- c(0, 1, 2, 0)
x1 <- c(1, 2, 3)
f1 <- stepfun(x = x1, y = y1)
print(class(f1))
# [1] "stepfun"  "function" #  OK!!!
plot(f1)

y2 <- c(0, 1, 0)
x2 <- c(1.5, 2.5)
f2 <- stepfun(x = x2, y = y2)
plot(f2)

fs <- function(x, f1, f2) {
  # y <- f1(x)   f2(x) #  OK
  # y <- as.stepfun(x = x, y = y, ties = "ordered", right = FALSE) # does not work
  # return(y) #           does not work
  return(f1(x)   f2(x))
}
print(class(fs)) # [1] "function"
# attributes(fs) # no new information...

fm <- function(x, f1, f2) {
  return(f1(x) * f2(x))
}
print(class(fm)) # [1] "function"

Example as. for data.frame which works as expected:

z <- c(1, 2)
class(z) #    [1] "numeric"
class(as.data.frame(z)) #    [1] "data.frame"

About internals of stepfun

function (x, y, f = as.numeric(right), ties = "ordered", right = FALSE) 
{
  if (is.unsorted(x)) 
    stop("stepfun: 'x' must be ordered increasingly")
  n <- length(x)
  if (n < 1) 
    stop("'x' must have length >= 1")
  n1 <- n   1L
  if (length(y) != n1) 
    stop("'y' must be one longer than 'x'")
  rval <- approxfun(x, y[-if (right) 
    n1
  else 1], method = "constant", yleft = y[1L], yright = y[n1], 
    f = f, ties = ties)
  class(rval) <- c("stepfun", class(rval))
  attr(rval, "call") <- sys.call()
  rval
}

CodePudding user response:

The fs function needs the "stepfun" class, not the results it returns. But your fs object won't work as a "stepfun" object, because R makes assumptions about those: they need to keep copies of the data that produced them, among other things. You can see what f1 keeps by looking at ls(environment(f1)). I don't know how those objects are used, but presumably they are needed.

Edited to add:

To turn fs into a "stepfun" object, you could try as.stepfun(fs). But this fails, with the error message

  Error in as.stepfun.default(fs) : 
no 'as.stepfun' method available for 'x'

The error message isn't the best (x is the internal name of the first argument, and in my opinion it would make more sense to say there's no method available for fs), but it's saying R doesn't know how to do the conversion you want.

CodePudding user response:

It looks like user2554330 is right about creating stepfun objects directly from two other stepfun objects, but here is a workaround in case it's useful:

x12 <- sort(unique(c(x1, x2)))
y12 <- f1(c(x12[1] - 1, x12))   f2(c(x12[1] - 1, x12))
f12 <- stepfun(x = x12, y = y12)
  • Related