ToNoY
ToNoY

Reputation: 1378

Producing all combinations of two column values in R

I have a data.frame with two columns

> data.frame(a=c(5,4,3), b =c(1,2,4))
  a b
1 5 1
2 4 2
3 3 4

I want to produce a list of data.frames with different combinations of those column values; there should be a total of six possible scenarios for the above example (correct me if I am wrong):

  a b
1 5 1
2 4 2
3 3 4

  a b
1 5 1
2 4 4
3 3 2

  a b
1 5 2
2 4 1
3 3 4

  a b
1 5 2
2 4 4
3 3 1

  a b
1 5 4
2 4 2
3 3 1

  a b
1 5 4
2 4 1
3 3 2

Is there a simple function to do it? I don't think expand.grid worked out for me.

Upvotes: 1

Views: 869

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388817

Using combinat::permn create all possible permutations of b value and for each bind it with a column.

df <- data.frame(a= c(5,4,3), b = c(1,2,4))
result <- lapply(combinat::permn(df$b), function(x) data.frame(a = df$a, b = x))
result

#[[1]]
#  a b
#1 5 1
#2 4 2
#3 3 4

#[[2]]
#  a b
#1 5 1
#2 4 4
#3 3 2

#[[3]]
#  a b
#1 5 4
#2 4 1
#3 3 2

#[[4]]
#  a b
#1 5 4
#2 4 2
#3 3 1

#[[5]]
#  a b
#1 5 2
#2 4 4
#3 3 1

#[[6]]
#  a b
#1 5 2
#2 4 1
#3 3 4

Upvotes: 1

ThomasIsCoding
ThomasIsCoding

Reputation: 101064

Actually expand.grid can work here, but it is not recommended since it's rather inefficient when you have many rows in df (you need to subset n! out of n**n if you have n rows).

Below is an example using expand.grid

u <- do.call(expand.grid, rep(list(seq(nrow(df))), nrow(df)))
lapply(
  asplit(
    subset(
      u,
      apply(u, 1, FUN = function(x) length(unique(x))) == nrow(df)
    ), 1
  ), function(v) within(df, b <- b[v])
)

One more efficient option is to use perms from package pracma

library(pracma)
> lapply(asplit(perms(df$b),1),function(v) within(df,b<-v))
[[1]]
  a b
1 5 4
2 4 2
3 3 1

[[2]]
  a b
1 5 4
2 4 1
3 3 2

[[3]]
  a b
1 5 2
2 4 4
3 3 1

[[4]]
  a b
1 5 2
2 4 1
3 3 4

[[5]]
  a b
1 5 1
2 4 2
3 3 4

[[6]]
  a b
1 5 1
2 4 4
3 3 2

Upvotes: 1

Related Questions