user2911296
user2911296

Reputation:

Looping through an id using lapply() in R

I have written a function like this:

myfunc <- function(data, c1, c2, c3) {
          res <- data*c1*c2*c3
          return(res)
          }   

To apply myfunc on the vector data I could use

lapply(data, myfunc, c1=2, c2=3, c3=4)

But I have to loop through an id along with the vector data, so that every row of the resulting vector (or matrix) contains an id and the respective result.

So for the simple case this would be:

myfunc <- function(id, data, c1, c2, c3) {
          res <- data*c1*c2*c3
          return(c(id, res))
          }   

But I cant use lapply on that. I already tried to put all input (id, data, c1, c2, c3) in a matrix to use apply:

apply(matrix, 1, myfunc)

But it did not work.

So what would be the best way to achieve this?

Thanks in advance!

EDIT:

This could be the data matrix:

      id data c1  c2  c3
 [1,] 32 1.12  2 2.5 2.8
 [2,] 33 1.14  2 2.5 2.8
 [3,] 34 1.21  2 2.5 2.8
 [4,] 35 1.22  2 2.5 2.8
 [5,] 36 1.27  2 2.5 2.8
 [6,] 37 1.30  2 2.5 2.8
 [7,] 38 1.32  2 2.5 2.8
 [8,] 39 1.36  2 2.5 2.8
 [9,] 40 1.44  2 2.5 2.8
[10,] 41 1.45  2 2.5 2.8

Column id shall get looped through and the myfunc shall be applied on the other columns. I expect (or demand) a result like this:

      id   res
 [1,] 32 15.68
 [2,] 33 15.96
 [3,] 34 16.94
 [4,] 35 17.08
 [5,] 36 17.78
 [6,] 37 18.20
 [7,] 38 18.48
 [8,] 39 19.04
 [9,] 40 20.16
[10,] 41 20.30

Upvotes: 0

Views: 698

Answers (4)

rnso
rnso

Reputation: 24545

Why not have data in a dataframe and then:

> ddf$res = with(ddf, data*c1*c2*c3)
> ddf
      id data c1  c2  c3   res
[1,]  32 1.12  2 2.5 2.8 15.68
[2,]  33 1.14  2 2.5 2.8 15.96
[3,]  34 1.21  2 2.5 2.8 16.94
[4,]  35 1.22  2 2.5 2.8 17.08
[5,]  36 1.27  2 2.5 2.8 17.78
[6,]  37 1.30  2 2.5 2.8 18.20
[7,]  38 1.32  2 2.5 2.8 18.48
[8,]  39 1.36  2 2.5 2.8 19.04
[9,]  40 1.44  2 2.5 2.8 20.16
[10,] 41 1.45  2 2.5 2.8 20.30

Upvotes: 0

Colonel Beauvel
Colonel Beauvel

Reputation: 31171

No need to use a function, using data.table here is an atomic example of your data:

library(data.table)

lst = list(id=c(32,33,34), data=c(1.12,1.14,1.21), c1=rep(2,3),c2=rep(2.5,3),c3=rep(2.8,3))
M = do.call(cbind, lst)

 #     id data c1  c2  c3
#[1,] 32 1.12  2 2.5 2.8
#[2,] 33 1.14  2 2.5 2.8
#[3,] 34 1.21  2 2.5 2.8

dt = as.data.table(M)

We can proceed with:

dt[,res:=data*c1*c2*c3]
as.matrix(dt[,list(id,res)])
#     id   res
#[1,] 32 15.68
#[2,] 33 15.96
#[3,] 34 16.94

Upvotes: 1

Vincent Guillemot
Vincent Guillemot

Reputation: 3429

I'd personally rather do it with an apply:

x <- data.frame(id = 32:41, 
                data = c(1.12, 1.14, 1.21, 1.22, 1.27, 1.3, 1.32, 1.36, 1.44, 1.45), 
                c1 = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), 
                c2 = c(2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5), 
                c3 = c(2.8, 2.8, 2.8, 2.8, 2.8, 2.8, 2.8, 2.8, 2.8, 2.8))
x$res <- apply(x[,-1],1,prod)
x[, c("id", "res")]

Upvotes: 1

Mhairi
Mhairi

Reputation: 1

Unless I'm being dumb this could be quite simple.

So, you understand how to use lapply to create the vector res, right? Just join it with your id column. They will be in the same order so the IDs will match up.

cbind(data$id, res)

Upvotes: 0

Related Questions