Elks
Elks

Reputation: 85

Create a matrix of all the combinations (order doesn't matter) of a vector keeping their place - R

I have a vector of fields

cuchars <- c('E', 'F', 'G')

I would like to be able to create strings with all the combinations where the order doesn't matter ('E','F' is the same as 'F','E').

I was able to create a matrix with all the combinations I need.

# make a dataframe with all our possible combinations
combi <- data.frame(matrix(nrow=0,ncol=length(cuchars)))
for(i in 1:length(cuchars)){
  combi.tmp <- t(combn(cuchars,i))
  combi <- rbind(combi,cbind(combi.tmp, matrix(nrow=nrow(combi.tmp), ncol=length(cuchars)-i ) ))
}

Out of these combinations I need to make a list of strings where the "place" does matter. Where the fields is not in the current combinations group I would like to add 'X as' before it.

what I have now is

for(i in 1:length(combi)){
   filter <- paste0(combi[i,][!is.na(combi[i,])],collapse=', ')
   missing <- setdiff(cuchars, paste0(combi[i,][!is.na(combi[i,])]))
   missing <- ifelse(length(missing) != 0 ,paste0( " 'X' as ", missing ,collapse=', '),'') 
   print( paste0( filter, ifelse(missing != '',paste0(', ',missing,collapse=', '),'') )
}

E,   'X' as F,  'X' as G
F,   'X' as E,  'X' as G
G,   'X' as E,  'X' as F
E,   F,         'X' as G
E,   G,         'X' as F
F,   G,         'X' as E
E,   F,          G

What I need it to look like is: (keep the order of E, F, and G)

E,         'X' as F,     'X' as G
'X' as E,  F,            'X' as G
'X' as E,  'X' as F,     G
E,         F,            'X' as G
E,         'X' as F,      G 
'X' as E,  F,             G
E,         F,             G

I'm fairly new to R, so if there is a better way of doing this I'd appreciate tips! Thanks!

Upvotes: 2

Views: 158

Answers (1)

flodel
flodel

Reputation: 89057

A good start is to do:

x1 <- cuchars
x2 <- sprintf("'X' as %s", cuchars)
expand.grid(Map(c, x1, x2))

#          E        F        G
# 1        E        F        G
# 2 'X' as E        F        G
# 3        E 'X' as F        G
# 4 'X' as E 'X' as F        G
# 5        E        F 'X' as G
# 6 'X' as E        F 'X' as G
# 7        E 'X' as F 'X' as G
# 8 'X' as E 'X' as F 'X' as G

If you did not want the last row, remove it using head:

head(expand.grid(Map(c, x1, x2)), -1)

The output is a data.frame with three columns. You can turn it into a character vector by doing:

do.call(paste, c(head(expand.grid(Map(c, x1, x2)), -1), sep = ", "))
# [1] "E, F, G"               "'X' as E, F, G"        "E, 'X' as F, G"       
# [4] "'X' as E, 'X' as F, G" "E, F, 'X' as G"        "'X' as E, F, 'X' as G"
# [7] "E, 'X' as F, 'X' as G"

Upvotes: 1

Related Questions