Anonymous
Anonymous

Reputation: 1968

Closure does not work inside "with"

demo <- data.frame(step = seq(1:5), x1 = sample(1:5, 5), x2 = sample(5:9, 5), xx = 0)

I have DF and would like to change one of its columns within "apply" but I do not want to use with global variable for this, thus, I am trying to pass environment inside FUN and assign variable within this environment.

# This method works but it looks like hardcode because I have to use global name "demo"
cycle <- function(k, d, e) { demo[k, 4] <<- k } 
lapply(1:nrow(demo), cycle, demo, environment())

These methods do not work :

# In this case R shows error - "k" is not defined, although, it should work as a closure
cycle <- function(k, d, e) { with(e, d[k, 4] <- k) }
lapply(1:nrow(demo), cycle, demo, environment())

# I tried "assign" new value to DF but this did not change it, "xx" column is still 0
cycle <- function(k, d, e) { assign("d[k, 4]", k, envir = e) }
lapply(1:nrow(demo), cycle, demo, environment())

# This also does not change values in last column
 cycle <- function(k, d, e) { assign(gsub("#", k, d), k, envir = e) }
 lapply(1:nrow(demo), cycle, "demo[#,4]", environment())

Question : how to change specific column in DF from FUN without using global name of this DF?

Just a suggestion, maybe I incorrectly define environment?

Update : I need to use "lapply" because I need to put several actions into one function and iteratively execute it for each row, e.g. I may want to apply PCA on floating window in similar way :

DF = data.frame(...)

x1 x2 x3 res
1  2  3  0
4  5  6  0
7  8  9  0

for (k in 1:3)
{
    x = DF[k:k + 2,]
    pc <- princomp(x, ...) 
    ls <- loadings(pc) # or ls <- lm(x + 0)
    values <- c(DF[k,1] * ls[1] + DF[k,2] * ls[2])
}

DF$res <- values

I need to execute this loop as a callback in "apply", how to get result (values) of this execution if I want to use "apply" instead of "for" loop?

As an example, I would like to have function like "applyWeeklySMA" in this article http://www.r-bloggers.com/structural-arbitrage-trading-the-equity-curve/ but I want to replace loop with "lapply", is this possible?

Upvotes: 0

Views: 44

Answers (1)

Nick Kennedy
Nick Kennedy

Reputation: 12640

DF <- as.data.frame(matrix(1:15, ncol = 3))

pcl <- function(k, data) {
    x <- data[k:(k + 2), ]
    pc <- princomp(x) 
    load <- loadings(pc)
    as.matrix(data[k, 1:2]) %*% load[1:2]
}

DF$res <- c(lapply(1:3, pcl, DF), rep(0, 2))

This is I think what you're trying to achieve. Note that the function pcl has no dependencies at all on the calling environment.

Upvotes: 1

Related Questions