1

I am working in R and am trying to take a dataframe with 7 columns and create a 2 column dataframe with all the combinations of each row's responses stacked on top of each other.

For example if I had:

1,0,1,0

I would want to transform that row to the rows

1,0

1,1

1,0

0,1

0,0

1,0

And do that to every row in the dataframe and stack them.

I know how to do this for 1 row at a time

df2<-combn(df[1,],2) 

That code will get me the combinations of one row like my example above; however I can't figure out how to do apply it to all rows. My best guess would be something along the lines of

df3<-apply(1:nrow(df), 1, function(x) combn(df[x,],2))

However I am getting the "dim(x) must have a positive length" error. Does anyone know what my problem is and can explain what I am doing wrong and why I need to do it a certain way. New to coding R beyond base functions. As far as data goes it's just binary data.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
dugant195
  • 13
  • 2
  • How about this? `df3 <- do.call(rbind, lapply(1:nrow(df), function(i) t(combn(df[i,],2))))` – Mike H. Apr 27 '17 at 14:08
  • Welcome to SO. Please have a look at [how to ask a good question](http://stackoverflow.com/help/how-to-ask), as well as how to make a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – Sotos Apr 27 '17 at 14:10
  • @MikeH. That worked! Thanks so much. However a couple questions about HOW is it is working if you have the time. why would lapply work and not regular apply? Is "i" functioning any different than "x" in my attempt? What is the purpose of the do.call function? I am unfamiliar with this function. I am assuming that rbind just gets it into the shape that I desire. Sorry I would like to understand how it is working if possible! – dugant195 Apr 27 '17 at 14:25
  • We use `lapply` to store the results of `combn` for each row in a list. Then I use `do.call` and `rbind` to stack all those results together. Try running just the `lapply(1:nrow(df), function(i) t(combn(df[i,],2)))` and you can get a visual idea of how it works – Mike H. Apr 27 '17 at 14:28
  • @MikeH. oh that makes its really clear running just that part of the code by itself. Thanks so much, figuring out which of the apply family functions to use can be tricky! – dugant195 Apr 27 '17 at 14:33

2 Answers2

0

Something like this:

df <- data.frame(a = c(1,0), b = c(0,1), c = c(1,0), d = c(0,1))
matrix(c(apply(df[1:2,],1, function(x) combn(x,2))), ncol = 2, byrow = T)
      [,1] [,2]
 [1,]    1    0
 [2,]    1    1
 [3,]    1    0
 [4,]    0    1
 [5,]    0    0
 [6,]    1    0
 [7,]    0    1
 [8,]    0    0
 [9,]    0    1
[10,]    1    0
[11,]    1    1
[12,]    0    1
Tobias Dekker
  • 980
  • 8
  • 19
0

Since you didn't provide sample data i'll use some made up data. You can use lapply to store each row as a list element and then use do.call with rbind to bind them all together:

set.seed(1)
df <- data.frame(col1 = sample(1:4), col2 = sample(1:4), col3 = sample(1:4), col4 = sample(1:4))

df3 <- do.call(rbind, lapply(1:nrow(df), function(i) t(combn(df[i,],2))))

head(df3)
#    [,1] [,2]
#[1,] 2    1   
#[2,] 2    3   
#[3,] 2    3   
#[4,] 1    3   
#[5,] 1    3   
#[6,] 3    3 

Note - df3 will return as a matrix.

Mike H.
  • 13,960
  • 2
  • 29
  • 39
  • Hey Mike, added a comment on your original post for this asking for some clarification for my own knowledge. However it worked! Thanks – dugant195 Apr 27 '17 at 14:28