编写循环以选择变量值的所有组合,以在R

时间:2018-12-13 19:17:21

标签: r for-loop random combinations permutation

我有以下四个方程(a,b,c,d),带有几个不同的变量(x,t,v,w,n,f)。我的目标是尝试找到所有将为方程式(a,b,c,d)生成所有正数(非零)的变量值集。常规循环只会遍历所生成序列的每个数字,并系统地检查它是否生成正值。我希望它从每个序列中选取随机数,并针对R中的其他序列进行测试。 例如(x = 8,t = 2.1,v = 13,w = 1,n = 10,f = 1)是一组可能的组合。

请不要建议对这些问题进行解析解决,然后再找出值。这些只是我要处理的方程式的简单表示。我拥有的方程式非常复杂,并且有15个以上的变量。

#Equations
a <- x * t - 2*x
b <- v - x^2 
c <- x - w*t - t*t 
d <- (n - f)/t

x <- seq(from = 0.0001, to = 1000, by = 0.1)
t <- seq(from = 0.0001, to = 1000, by = 0.1)
v <- seq(from = 0.0001, to = 1000, by = 0.1)
w <- seq(from = 0.0001, to = 1000, by = 0.1)
n <- seq(from = 0.0001, to = 1000, by = 0.1)
f <- seq(from = 0.0001, to = 1000, by = 0.1)

2 个答案:

答案 0 :(得分:3)

首先,最好将方程式和探测值组织成列表:

set.seed(1222)

values <- list(x = x, t = t, v = v, w = w, n = n, f = f)

eqs <- list(
  a = expression(x * t - 2 * x),
  b = expression(v - x^2), 
  c = expression(x - w*t - t*t), 
  d = expression((n - f)/t)
)

然后,我们可以定义从每个探针向量中随机抽取的样本数量:

samples <- 3
values.sampled <- lapply(values, sample, samples)

$x
[1] 642.3001 563.1001 221.3001

$t
[1] 583.9001 279.0001 749.1001

$v
[1] 446.6001 106.7001   0.7001

$w
[1] 636.0001 208.8001 525.5001

$n
[1] 559.8001  28.4001 239.0001

$f
[1] 640.4001 612.5001 790.1001

然后,我们可以遍历每个存储的方程式,在“采样”环境中评估方程式:

results <- sapply(eqs, eval, envir = values.sampled)

            a          b         c          d
[1,] 373754.5 -412102.82 -711657.5 -0.1380373
[2,] 155978.8 -316975.02 -135533.2 -2.0935476
[3,] 165333.3  -48973.03 -954581.8 -0.7356827

您可以从此处删除等于或小于0的任何值:

results[results <= 0] <- NA

答案 1 :(得分:1)

如果每个独立的值都可以取相同的值(例如seq(from = 0.0001, to = 1000, by = 0.1)),则我们可以更严格地解决此问题,并避免产生重复项的可能性。首先,我们创建一个masterFun,它实际上是您要定义的所有函数的包装器:

masterFun <- function(y) {
    ## y is a vector with 6 values
    ## y[1] -->> x
    ## y[2] -->> t
    ## y[3] -->> v
    ## y[4] -->> w
    ## y[5] -->> n
    ## y[6] -->> f

    fA <- function(x, t) {x * t - 2*x}
    fB <- function(v, x) {v - x^2}
    fC <- function(x, w, t) {x - w*t - t*t}
    fD <- function(n, f, t) {(n - f)/t}

    ## one can easily filter out negative
    ## results as @jdobres has done.

    c(a = fA(y[1], y[2]), b = fB(y[3], y[1]), 
      c = fC(y[1], y[4], y[2]), d = fD(y[5], y[6], y[2]))
}

现在,使用permuteSample,它能够生成向量的随机排列,然后将RcppAlgos(我是作者)中的每个给定排列的用户定义函数应用于每个排列,我们有:

## Not technically the domain, but this variable name
## is concise and very descriptive
domain <- seq(from = 0.0001, to = 1000, by = 0.1)

library(RcppAlgos)

          ## number of variables ... x, t, v, w, n, f
          ##           ||
          ##           \/
permuteSample(domain, m = 6, repetition = TRUE,
                 n = 3, seed = 123, FUN = masterFun)
[[1]]
            a              b              c              d 
218830.316100 -608541.146040 -310624.596670      -1.415869 

[[2]]
            a              b              c              d 
371023.322880 -482662.278860 -731052.643620       1.132836 

[[3]]
             a               b               c               d 
18512.60761001 -12521.71284001 -39722.27696002     -0.09118721

简而言之,底层算法能够生成 n th lexicographical结果,这使我们能够应用来自1 to "# of total permutations"的映射排列本身。例如,给定向量1:3的排列:

permuteGeneral(3, 3)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    1    3    2
[3,]    2    1    3
[4,]    2    3    1
[5,]    3    1    2
[6,]    3    2    1

我们可以轻松生成上面的 2 nd 5 th 排列,而无需生成第一个排列或前四个排列:

permuteSample(3, 3, sampleVec = c(2, 5))
     [,1] [,2] [,3]
[1,]    1    3    2
[2,]    3    1    2

这使我们能够对随机样本有更可控制和切实的把握,因为我们现在可以以更熟悉的方式(即数字的随机样本)来思考它们。

如果您实际上想查看上述计算中使用了哪些变量,我们只需删除FUN参数:

permuteSample(domain, m = 6, repetition = TRUE, n = 3, seed = 123)
         [,1]     [,2]     [,3]     [,4]     [,5]     [,6]
[1,] 780.7001 282.3001 951.5001 820.8001 289.1001 688.8001
[2,] 694.8001 536.0001  84.9001 829.2001 757.3001 150.1001
[3,] 114.7001 163.4001 634.4001  80.4001 327.2001 342.1001