2

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!

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Claudia M.
  • 333
  • 1
  • 2
  • 8
  • @nongkrong Thanks. I think I am using `lapply` over a `list` of dataframes, with the intention of applying the function `append` to each `dataframe` element. Indeed, `append` takes two dataframes as inputs and gives a dataframe as output. In short, I am not sure I understand your comment and why it explains my `lapply` failure. Could you please elaborate? – Claudia M. Aug 12 '15 at 17:19
  • Try `lapply(list1,function(x)apply(x[[1]],x[[2]]))` – MichaelChirico Aug 12 '15 at 17:27
  • @MichaelChirico Thanks, Michael. Just a clarification: did you mean `lapply(list1, function(x) append(x[[1]], x[[2]]))`? Also, what is `x`? Can you please explain? Thank you. – Claudia M. Aug 12 '15 at 17:32
  • your data1-data4 are matrices not data.frames, correct? – Rorschach Aug 12 '15 at 17:34
  • They are `data.frames`. – Claudia M. Aug 12 '15 at 17:38
  • `x` is the argument you pass to the anonymous/inline function defined as `apply(x[[1]], x[[2]] )`; it appears I misunderstood your intent, so it won't work quite as I thought. – MichaelChirico Aug 12 '15 at 17:45

2 Answers2

1

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.

arvi1000
  • 9,393
  • 2
  • 42
  • 52
1

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)
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214