Skip to content

More elegant way of stacking the data

4 messages · Dimitri Liakhovitski, David Winsemius, Chel Hee Lee

#
I have the data frame 'df' and my desired solution 'out'.
I am sure there is a more elegant R-way to do it - without a loop.

df = data.frame(a=1:5,b=letters[1:5],c1=1:5,c2=2:6,c3=3:7,c4=4:8)
mylist=NULL
for(i in 1:4){
  myname<-paste("c",i,sep="")
  mylist[[i]]<-df[c("a","b",myname)]
  names(mylist[[i]])<-c("a","b","c")
}
out<-do.call(rbind,mylist)
out

Thank you!
#
On Nov 24, 2014, at 3:12 PM, Dimitri Liakhovitski wrote:

            
Observe the wonders of recycling in dataframes. If you wanted to drop the last column from this it would be the same modulo changing one column nmae.

 cbind( df[1:2], stack(df[-c(1:2)] )  )
#
   a b values ind
1  1 a      1  c1
2  2 b      2  c1
3  3 c      3  c1
4  4 d      4  c1
5  5 e      5  c1
6  1 a      2  c2
7  2 b      3  c2
8  3 c      4  c2
9  4 d      5  c2
10 5 e      6  c2
11 1 a      3  c3
12 2 b      4  c3
13 3 c      5  c3
14 4 d      6  c3
15 5 e      7  c3
16 1 a      4  c4
17 2 b      5  c4
18 3 c      6  c4
19 4 d      7  c4
20 5 e      8  c4
#
If you do not want to use the loop, a function called 'reshape' may be 
useful:

 > df <- data.frame(a=1:5,b=letters[1:5],c1=1:5,c2=2:6,c3=3:7,c4=4:8)
 > out2 <- reshape(data=df, direction="long", varying=list(3:6), 
times=paste("c",1:4,sep=""))
 > out2
      a b time c1 id
1.c1 1 a   c1  1  1
2.c1 2 b   c1  2  2
3.c1 3 c   c1  3  3
4.c1 4 d   c1  4  4
5.c1 5 e   c1  5  5
1.c2 1 a   c2  2  1
2.c2 2 b   c2  3  2
3.c2 3 c   c2  4  3
4.c2 4 d   c2  5  4
5.c2 5 e   c2  6  5
1.c3 1 a   c3  3  1
2.c3 2 b   c3  4  2
3.c3 3 c   c3  5  3
4.c3 4 d   c3  6  4
5.c3 5 e   c3  7  5
1.c4 1 a   c4  4  1
2.c4 2 b   c4  5  2
3.c4 3 c   c4  6  3
4.c4 4 d   c4  7  4
5.c4 5 e   c4  8  5

I hope this helps.

Chel Hee Lee
On 11/24/2014 5:12 PM, Dimitri Liakhovitski wrote:
#
Thanks a lot, guys!
On Tue, Nov 25, 2014 at 9:42 AM, Lee, Chel Hee <chl948 at mail.usask.ca> wrote: