Hi, I very frequently end up in a situation where I have a named list of data.frames that I wish to combine. e.g. l <- list(A=data.frame(x=rnorm(5), y=rnorm(5)), B=data.frame(x=rnorm(3),y=rnorm(3)), C=data.frame(x=rnorm(4),y=rnorm(4)), D=data.frame(x=rnorm(7),y=rnorm(7))) I would like to combine these data.frames into a single data.frame, with the column-names. This is easy with rbind and do.call l2 <- do.call(rbind,l) However, I would also like l2 to contain a column containing the names in the original list? Is there a more elegant way to do this than: l2 <- do.call(rbind,l) l2$name <- rep(names(l),times=sapply(l,nrow)) Mark
Hello, There's nothing inelegant in your solution, you're using vectorized instructions. But there's a bug. The argument to rep should be 'each', not 'times'. l2$name <- rep(names(l), each=sapply(l,nrow)) Hope this helps, Rui Barradas Em 30-10-2012 08:16, Mark Payne escreveu:> Hi, > > I very frequently end up in a situation where I have a named list of > data.frames that I wish to combine. e.g. > > l <- list(A=data.frame(x=rnorm(5), > y=rnorm(5)), > B=data.frame(x=rnorm(3),y=rnorm(3)), > C=data.frame(x=rnorm(4),y=rnorm(4)), > D=data.frame(x=rnorm(7),y=rnorm(7))) > > I would like to combine these data.frames into a single data.frame, > with the column-names. This is easy with rbind and do.call > > l2 <- do.call(rbind,l) > > However, I would also like l2 to contain a column containing the names > in the original list? Is there a more elegant way to do this than: > > l2 <- do.call(rbind,l) > l2$name <- rep(names(l),times=sapply(l,nrow)) > > > Mark > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Hello, You're right, sorry for the misleading post. It's even documented: "|times||A |integer vector giving the (non-negative) number of times to repeat each element if of length |length(x)|" As for a one liner, use within(). within(do.call(rbind, l), name <- rep(names(l), times=sapply(l, nrow))) Hope this helps, Rui Barradas Em 30-10-2012 10:40, Mark Payne escreveu:> Hi Rui, > > Thanks for the reply. I guess I was mainly wondering if there was a > one-line approach buried away there somewhere that I had overlooked.. > > Regarding the each argument, I initially used each as well - however, > as it turns out, times is actually the correct argument. e.g. > >> rep(letters[1:5],each=5:1) > [1] "a" "a" "a" "a" "a" "b" "b" "b" "b" "b" "c" "c" "c" "c" "c" "d" > "d" "d" "d" "d" "e" "e" "e" "e" "e" > Warning message: > In rep(letters[1:5], each = 5:1) : first element used of 'each' argument >> rep(letters[1:5],times=5:1) > [1] "a" "a" "a" "a" "a" "b" "b" "b" "b" "c" "c" "c" "d" "d" "e" > Apparently each can't be more than length 1, but if length(x) and > length(times) are the same, then it repeats each individual element > the given number of times > > Cheers, > > Mark > > On 30 October 2012 11:30, Rui Barradas <ruipbarradas@sapo.pt> wrote: >> Hello, >> >> There's nothing inelegant in your solution, you're using vectorized >> instructions. >> But there's a bug. The argument to rep should be 'each', not 'times'. >> >> l2$name <- rep(names(l), each=sapply(l,nrow)) >> >> Hope this helps, >> >> Rui Barradas >> Em 30-10-2012 08:16, Mark Payne escreveu: >>> Hi, >>> >>> I very frequently end up in a situation where I have a named list of >>> data.frames that I wish to combine. e.g. >>> >>> l <- list(A=data.frame(x=rnorm(5), >>> y=rnorm(5)), >>> B=data.frame(x=rnorm(3),y=rnorm(3)), >>> C=data.frame(x=rnorm(4),y=rnorm(4)), >>> D=data.frame(x=rnorm(7),y=rnorm(7))) >>> >>> I would like to combine these data.frames into a single data.frame, >>> with the column-names. This is easy with rbind and do.call >>> >>> l2 <- do.call(rbind,l) >>> >>> However, I would also like l2 to contain a column containing the names >>> in the original list? Is there a more elegant way to do this than: >>> >>> l2 <- do.call(rbind,l) >>> l2$name <- rep(names(l),times=sapply(l,nrow)) >>> >>> >>> Mark >>> >>> ______________________________________________ >>> R-help@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide >>> http://www.R-project.org/posting-guide.html >>> and provide commented, minimal, self-contained, reproducible code. >>[[alternative HTML version deleted]]
Hi, You can also try this: ?res<-do.call(rbind,lapply(l,function(x) data.frame(Name=names(l)[match.call()[[2]][[3]]],x))) ?row.names(res)<-1:nrow(res) ?head(res) #? Name????????? x????????? y #1??? A -0.7326214 -0.8871683 #2??? A? 0.4761960? 0.8245219 #3??? A? 0.2362935 -0.1427997 #4??? A? 1.1684286 -0.3849312 #5??? A -0.5440966 -0.8001079 #6??? B? 0.3652238 -0.9604054 A.K. ----- Original Message ----- From: Mark Payne <markpayneatwork at gmail.com> To: r-help at r-project.org Cc: Sent: Tuesday, October 30, 2012 4:16 AM Subject: [R] Named list of data.frames to data.frame with names Hi, I very frequently end up in a situation where I have a named list of data.frames that I wish to combine. e.g. l <- list(A=data.frame(x=rnorm(5), y=rnorm(5)), ? ? ? ? ? B=data.frame(x=rnorm(3),y=rnorm(3)), ? ? ? ? ? C=data.frame(x=rnorm(4),y=rnorm(4)), ? ? ? ? ? D=data.frame(x=rnorm(7),y=rnorm(7))) I would like to combine these data.frames into a single data.frame, with the column-names. This is easy with rbind and do.call l2 <- do.call(rbind,l) However, I would also like l2 to contain a column containing the names in the original list? Is there a more elegant way to do this than: l2 <- do.call(rbind,l) l2$name <- rep(names(l),times=sapply(l,nrow)) Mark ______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.