Reputation: 244
This seems like a straightforward problem, but I'm having trouble finding a solution here on Stack Overflow. I have a data frame df
with columns of data a
and b
. I have a complex function (simplified example below) that I want to apply to all rows using mapply
. The problem I'm having is that I want to take an average of the n
and n-1
rows of b
as an input into the function, in place of b
. Here is an example
new.fun <- function( a, b ) { a * b }
a <- seq( from = 1, to = 10, by = 1 )
df <- data.frame( a , b = a * 10 )
mapply( new.fun, df$a, df$b )
Short of making a new column with the average of n
and n-1
(something that I only know how to do with a for
loop) and using that as an input, or creating a for
loop, is there a way to do this in a more "R-like" manner?
EDIT: Sorry, I forgot to add in the expected answer for the above example. The averages of b[1:2]
, b[2:3]
, etc. should be:
b2 <- c( 0, seq( from = 15, to = 95, by = 10 ) )
EDIT2: Had the wrong number of terms in here....set first term to 0 for these purposes
And the solution to the whole question should be:
> new.fun( df$a, b2 )
[1] 0 30 75 140 225 330 455 600 765 950
Sorry for the confusing series of posts here. Apparently I'm not describing the problem precisely. I want one variable within my mapply
call to consist not of the value in a particular row of the column within df
, but of an average of the nth
row and the n-1
row, basically a moving average of the row and preceding row, but I'm wondering if it can be packaged within the mapply
call in some clever way?
Upvotes: 0
Views: 85
Reputation: 388982
We can use rollmean
from zoo
package to calculate the rolling mean for b
column and then multiply it with a
column. (Similar to what @Sotos mentioned in comments.)
library(zoo)
df$a * c(0, rollmean(df$b, 2))
#[1] 0 30 75 140 225 330 455 600 765 950
Or by using the mapply
function
mapply(new.fun, df$a, c(0, rollmean(df$b, 2))
Upvotes: 0
Reputation: 57686
zoo::rollapply
is a very heavyweight (and slow) solution to a lightweight problem.
with(df, {
bmean <- c(NA, (b[-1] + b[-length(b)])/2) # replace NA with desired initial value
mapply(new.fun, a, bmean)
})
Upvotes: 2
Reputation:
lapply(seq(2, nrow(df)), function (i) {
mean_a <- mean(df$a[(i-1):i])
mean_b <- mean(df$b[(i-1):i])
new.fun(mean_a, mean_b)
})
You could use sapply
if you know the length of output your function is going to produce.
See also zoo::rollapply
.
Upvotes: 1