JJL
JJL

Reputation: 342

Generate unique combinations of rows where each row is treated as an individual split by a variable

I want to treat each row as a single element when creating unique combinations. Each combination should be between a Left and a Right only. So the first row in the example can be combined with the last two rows only, and the second row can be combined with the last two rows only.

Previously someone helped me with the following code, but it only creates combinations by rows when I need it between Left and Right rows.:

combs <- combn(1:nrow(df1), 2)
do.call(rbind, Map(function(i,j) cbind(df1[i,],df1[j,]), combs[1,], combs[2,]))

Say I have a dataframe with the following:

Side    Var1    Var2
Left     b        a
Left     a        b
Right    b        a
Right    a        b

and I want the following combinations in a single dataframe:

Side    Var1    Var2    Side     Var1   Var2
Left    b        a      Right      b        a
Left    b        a      Right      a        b
Left    a        b      Right      b        a
Left    a        b      Right      a        b

Upvotes: 0

Views: 96

Answers (2)

JJL
JJL

Reputation: 342

Slightly modified from Heroka to account for different amount of left and rights and reorders so each left/right variables are next to each other:

n_varsleft <- length(unique(sortdata[sortdata$Side == 'left',][,1]))
n_varsright <- length(unique(sortdata[sortdata$Side == 'right',][,1]))
indices <- expand.grid(1:n_varsleft, 1:n_varsright)
left <- sortdata[sortdata$Side == 'left',]
right <- sortdata[sortdata$Side == 'right',]
res <- cbind(left[indices[,1],], right[indices[,2],])
res <- res[,order(names(res))]

Upvotes: 0

Heroka
Heroka

Reputation: 13149

There is probably a more elegant way, but this gives the desired output.

First, we count how many 'unique' variables we have #assuming this is the same for Var1 and Var2

n_vars <- length(unique(dat$Var1))

Then we create a datafram of combinations of indices using expand.grid

#create indices
indices <- expand.grid(1:n_vars,1:n_vars)

And use those to create our output:

#create sub-dataframes
left <- dat[dat$Side=="Left",]
right <- dat[dat$Side=="Right",]

#cbind them together, using our indices to select rows
res <- cbind(left[indices[,1],],right[indices[,2],])
res
# Side Var1 Var2  Side Var1 Var2
# 1   Left    b    a Right    b    a
# 2   Left    a    b Right    b    a
# 1.1 Left    b    a Right    a    b
# 2.1 Left    a    b Right    a    b

Upvotes: 1

Related Questions