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.