Claudia M.
Claudia M.

Reputation: 353

R: using lapply with data frames and custom function

I have a question about using lapply with lists of dataframes. Suppose I have two lists:

 list1<-list(data1,data2)
 list2<-list(data3,data4)

I want to write a function that appends a column and row from one dataframe to another. This is my function:

append<-function(origin.data, destin.data){

vec.to.append<-origin.data[,1]

#add as the first column
destin.data<-cbind(vec.to.append, destin.data)

#add as first row
vec.to.append<-t(c(0, vec.to.append))
destin.data<-rbind(vec.to.append, destin.data)

return(destin.data)
}

This works fine if I run

append(list1[[1]], list2[[1]])

or

append(list1[[2]], list2[[2]])

but gives me an error when I try to use lapply:

trial<-lapply(list1, append, destin.data=list2)

The error looks straightforward:

Error in rbind(vec.to.append, destin.data) : number of columns of matrices must match (see arg 2)

but as I checked the dimensions of my dataframes and vector, all looked fine. Plus, the function runs and gives the expected result if I do not use lapply but do it "argument by argument". Can somebody help me out?

By the way, I saw the answer here: Using lapply with changing arguments but applying my function over the list names gives an empty result:

prova<-lapply(names(list1), append, destin.data=list2)

prova
list()

Clearly, I am missing something!

Upvotes: 3

Views: 2177

Answers (2)

arvi1000
arvi1000

Reputation: 9592

lapply(list1, append, destin.data=list2) is equivalent to:

list(append(list1[[1]], list2),
     append(list1[[2]], list2)

Which is not what you want. If you want to pair up list1 and list2, element-wise, you should do:

lapply(seq_along(list1), function(i) append(list1[[i]], list2[[i]])

This is equivalent to:

list(append(list1[[1]], list2[[1]]),
     append(list1[[2]], list2[[2]])

which is what you do want, right?

edit: as the other answer says, you can also use mapply, which is a little tidier, but this is the lapply-based solution. Result is the same in either case.

Upvotes: 1

Konrad Rudolph
Konrad Rudolph

Reputation: 546073

lapply only iterates over one list. The last argument you pass is passed on to the function as-is (i.e. the function append gets passed all of list2 rather than just one element).

You can use Map or mapply instead. Note that the order of the arguments here is reversed in comparison to lapply:

result = Map(append, list1, list2)

Upvotes: 1

Related Questions