【问题标题】:Write a loop to select all combination of variable values generating positive equation values in R编写一个循环来选择变量值的所有组合,在 R 中生成正方程值
【发布时间】:2019-05-15 01:43:30
【问题描述】:

我有以下四个方程 (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)

【问题讨论】:

    标签: r for-loop random combinations permutation


    【解决方案1】:

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

    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
    

    【讨论】:

    • 最后一点这行得通吗? resultsfinal &lt;- ifelse(results &gt; 0, results, NULL)
    • 我需要设置.seed,还是像我在问题中所做的那样指定值?
    • set.seed 只是为了让这个例子可以重现。它将使对sample 的调用始终返回相同的结果。在实践中,您可能不希望这样,但随着分析的完成,它会派上用场,以确保您始终获得相同的结果(即,用于发布)。
    • 这有点令人困惑。没有设置种子,我认为计算机不理解“eval”在做什么。这是我的代码卡住了rextester.com/ZJRHQ60262
    • 在您的链接代码中,您在主环境中创建了一个名为r 的变量,但不要将其复制到列表版本中。所以lapply 使用了r 的未采样副本,它的值太多。这使得results 成为一个列表,其中每个方程的结果具有不同数量的值,不能用索引替换([ ])。我的建议是直接在列表中使用seq,即list(a = seq(1, 10, 1)...
    【解决方案2】:

    如果每个独立的值都可以取相同的值(例如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
    

    简而言之,底层算法能够生成 nth 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
    

    我们可以很容易地生成上面的 2nd5th 排列,而无需生成第一个排列或前四个排列:

    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
    

    【讨论】:

      猜你喜欢
      • 2022-11-18
      • 2021-11-28
      • 2018-01-25
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      • 2013-05-21
      • 2021-12-08
      • 1970-01-01
      相关资源
      最近更新 更多