简体   繁体   中英

How to get all combinations matrix of x taken m with r?

With r, it is easy to generate all combinations of the elements of x taken m at a time.

> combn(c(0.4, 0.3, 0.7), 2)
      [,1] [,2] [,3]
 [1,]  0.4  0.4  0.3
 [2,]  0.3  0.7  0.7

But I actually would like something slightly different. I would like to have the same matrix but adding (1-x) if the element is not selected. With the previous example I would give:

> specialcombn(c(0.4, 0.3, 0.7), 2)
      [,1]      [,2]    [,3]
 [1,]  0.4      0.4    (1-0.4)
 [2,]  0.3     (1-0.3) 0.3
 [3,]  (1-0.7)  0.7    0.7

I wrote (1-0.7) ... to be more explicit, but I actually only need the value, here (1-0.7) = 0.3 :p

I could do this with loops and a hight complexity. I am interested in a good (possibly the optimal) solution.

Here's a pretty general approach which will return a nicely-ordered matrix:

set <- c(0.4, 0.3, 0.7, 2, 0)    # set to pick from
pick <- 3                        # how many items to pick
comb <- combn(set, pick)         # record combinations
# build matrix repeating the set once for each combination
x <- matrix(rep(set, ncol(comb)), nrow = length(set), ncol = ncol(comb))
# build a Boolean mask of values _not_ in each combination
mask <- apply(comb, 2, function(y){!set %in% y})
x[mask] <- 1 - x[mask]          # use mask to subtract those numbers from 1
x
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]  0.4  0.4  0.4  0.4  0.4  0.4  0.6  0.6  0.6   0.6
# [2,]  0.3  0.3  0.3  0.7  0.7  0.7  0.3  0.3  0.3   0.7
# [3,]  0.7  0.3  0.3  0.7  0.7  0.3  0.7  0.7  0.3   0.7
# [4,] -1.0  2.0 -1.0  2.0 -1.0  2.0  2.0 -1.0  2.0   2.0
# [5,]  1.0  1.0  0.0  1.0  0.0  0.0  1.0  0.0  0.0   0.0

If you're using it for very large matrices, the bottleneck will likely be %in% , which could likely be replaced with set operations. Other than that, everything should be pretty snappy.


If you don't care about order, you can skip building x and the mask, and just rbind 1 - the extra terms directly to comb :

rbind(comb, apply(comb, 2, function(x){1 - (set[!set %in% x])}))
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]  0.4  0.4  0.4  0.4  0.4  0.4  0.3  0.3  0.3   0.7
# [2,]  0.3  0.3  0.3  0.7  0.7  2.0  0.7  0.7  2.0   2.0
# [3,]  0.7  2.0  0.0  2.0  0.0  0.0  2.0  0.0  0.0   0.0
# [4,] -1.0  0.3  0.3  0.7  0.7  0.7  0.6  0.6  0.6   0.6
# [5,]  1.0  1.0 -1.0  1.0 -1.0  0.3  1.0 -1.0  0.3   0.7

Note that order within columns is now irregular. Regardless, either should work with a set and pick of any given size.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM