Reputation: 733
I want to create a new dataframes such that
df1
A1 B1 C1
1 2 3
4 5 6
7 8 9
result_df
A1 B1 C1 A2 B2 C2
1 2 3 4 5 6
1 2 3 7 8 9
4 5 6 7 8 9
Basically, pairwise combination of rows such that row[i] != row [j] I can do this using for loop. But I was wondering is there a way I can use data.table or apply function to make it faster.
Upvotes: 2
Views: 1117
Reputation: 6171
If it's always numbers in your data frame then you can use the following
## Generate data
DF <- as.data.frame(matrix(1:9,3))
DF
V1 V2 V3
1 1 4 7
2 2 5 8
3 3 6 9
Then combine the rows
t(apply(t(combn(3,2)), 1, FUN = function(x){unlist(DF[x])}))
which yields this matrix
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 1 2 3 7 8 9
[3,] 4 5 6 7 8 9
If you need non-numeric columns in your data frame then the code above needs to be tweaked a bit.
Update based on the comment below
To make the input identical to the OP we just need to make sure that we extract rows instead of columns in the function call
DF <- as.data.frame(matrix(1:9,3,byrow=TRUE))
t(apply(t(combn(3,2)), 1, FUN = function(x){unlist(DF[x,])}))
which produces
V11 V12 V21 V22 V31 V32
[1,] 1 4 2 5 3 6
[2,] 1 7 2 8 3 9
[3,] 4 7 5 8 6 9
The order becomes different but the result is the same.
Upvotes: 4
Reputation: 93813
A solution that won't force different columns to all be the same type:
DF <- as.data.frame(matrix(1:9,3,byrow=TRUE))
cmb <- combn(seq_len(nrow(DF)), 2)
cbind(DF[cmb[1,],], DF[cmb[2,],])
# V1 V2 V3 V1 V2 V3
#1 1 2 3 4 5 6
#1.1 1 2 3 7 8 9
#2 4 5 6 7 8 9
Upvotes: 2