Anonymous
Anonymous

Reputation: 1998

Iterate by row without FOR - not generic function for "apply"

# Custom DF
demo <- data.frame(step = seq(1:5), x1 = sample(1:5, 5), x2 = sample(5:9, 5))

# Add column with a result of some operation on subset before this row
demo <- transform(demo, res = 0)

# Fill in "res" with result of operation on several rows (subset) and some coefficients
for (k in 2:nrow(demo)) demo$res[k] <- demo$x1[k] * 2.0 + demo$x1[k - 1] * 3.0

Question : Is it possible to replace loop with "apply" or any other iterator with these conditions

I can simulate index this way :

cycle <- function(k) { k }
lapply(1:nrow(demo), cycle) # use sequence instead of DF itself

This code will print indices from 1 to 5 but how to pass demo as argument into "cycle"?

Upvotes: 0

Views: 68

Answers (1)

MrFlick
MrFlick

Reputation: 206616

There's no one-size-fits-all solution to this type of problem. In this particular case you don't need for loops or apply. You can just use vectored operations

demo$res <- c(0,tail(demo$x1,-1)*2 + head(demo$x1,-1)*3)

The dplyr library has nice lead/lag functions which can make these operations easier.

library(dplyr)
demo %>% mutate(res2=x1*2 + lag(x1)*3)
# this values the first value as NA rather than 0

It is also possible to pass additional arguments to function in lapply. For example you can do

cycle <- function(k, d) { paste(k, d[[1]][k]) }
lapply(1:nrow(demo), cycle, demo)

The parameters that are being iterated over are passed as the first parameter, and then you can just include additional parameters in the lapply call itself and they are passed along to the child function.

Upvotes: 2

Related Questions