0

I have a data frame which looks like this

 aa   bb      
 --------
 a    1   
 a    2   
 a    3   
 b    4       
 b    5    
 b    1    

I want above data frame to have a pair of elements picked from 'bb' and look like the below frame

 aa   bb   cc   
 -------------
 a    1    2   
 a    1    3   
 a    2    3   
 b    4    5  
 b    4    1   
 b    5    1   

R input code

d1 <- read.table(header = TRUE, sep = ";", text = 
"aa;bb
 a;1   
 a;2   
 a;3   
 b;4       
 b;5    
 b;1"   )
user2575429
  • 111
  • 2
  • 3
  • 8
  • 1
    Please explain the logic behind column "cc" in more detail – talat Dec 16 '15 at 15:39
  • I guess this should get you the result `library(data.table);setDT(d1)[,{tmp <- combn(bb,2); list(bb= tmp[1,], cc= tmp[2,]) } , by = aa]` (based on @Ananda Mahto's comments – akrun Dec 16 '15 at 15:42

3 Answers3

4

Using @Ananda Mahto's generous comments about the combn, we convert the 'data.frame' to 'data.table' (setDT(d1)), grouped by 'aa', we get the pairwise combinations of 'bb' (combn(bb,2)), extract the rows from it to create the 'bb' and 'cc'.

library(data.table)
setDT(d1)[,{tmp <- combn(bb,2)
           list(bb= tmp[1,], cc= tmp[2,]) } , by = aa]
#   aa bb cc
#1:  a  1  2
#2:  a  1  3
#3:  a  2  3
#4:  b  4  5
#5:  b  4  1
#6:  b  5  1
akrun
  • 874,273
  • 37
  • 540
  • 662
3

Using dplyr:

library(dplyr)

d1 %>% group_by(aa) %>%
       do(data.frame(t(combn(.[["bb"]], 2))))

Source: local data frame [6 x 3]
Groups: aa [2]

                  aa    X1    X2
              (fctr) (dbl) (dbl)
1                  a     1     2
2                  a     1     3
3                  a     2     3
4                  b     4     5
5                  b     4     1
6                  b     5     1
jeremycg
  • 24,657
  • 5
  • 63
  • 74
2

Only base R.

d2 <- t(do.call(cbind, tapply(d1$bb, d1$aa, function(x)combn(x, 2))))
rownames(d2) <- d1$aa
d2
#   [,1] [,2]
# a    1    2
# a    1    3
# a    2    3
# b    4    5
# b    4    1
# b    5    1
Ven Yao
  • 3,680
  • 2
  • 27
  • 42