【问题标题】:Append rle result from loop从循环中追加 rle 结果
【发布时间】:2012-10-05 06:30:31
【问题描述】:

我正在运行一个掷硬币模拟,循环运行大约 100 万次。

每次运行循环时,我都希望保留 RLE 命令的表输出。不幸的是,一个简单的附加似乎并不合适。每次我运行循环时,我得到的数据量都略有不同,这似乎是症结之一。

这段代码让我知道我在做什么:

N <- 5 #Number of times to run
rlex <-NULL
#begin loop#############################
for (i in 1:N) { #tells R to repeat N number
x <-sample(0:1, 100000, 1/2)
rlex <-append(rlex, rle(x))
}
table(rlex) #doesn't work
table(rle(x)) #only 1

因此,我想要一个合并的 rle 表,而不是拥有五个单独的 rle 结果(在此模拟中,完整版为 100 万)。希望这很清楚。显然我的实际代码有点复杂,因此任何解决方案都应该尽可能接近我指定的。

更新:循环是绝对要求。没有如果或但是。也许我可以提取 table(rle(x)) 数据并将其放入矩阵中。然而,同样的绊脚石是一些不太频繁的运行长度并不总是在每个循环中出现。因此,我想我希望根据运行长度数有条件地填充矩阵?

我放弃之前的最后一次更新:保留 rle$values 将意味着保留了太多数据。我的模拟是大规模的,我真的只希望保留 rle 的表输出。要么我为每个循环保留每个表(rle(x))并手动组合(会有数千个),要么我找到一种编程方式来保存数据(对于零和一来说是)并拥有一个由以下组成的表在我进行的过程中合并每个单独的循环。

要么按照规定,这很容易做到,要么我不会这样做。这似乎是一个愚蠢的想法/要求,但这应该与是否可以完成无关。

上次说真的。这是一个动画 gif,显示了我期望发生的事情。

在循环的每次迭代之后,数据被添加到表中。这一点我将能够传达的很清楚。

【问题讨论】:

  • 如果您使用 for 循环,我建议您预先分配 rlex 变量以适应结果。这将使事情运行得更快。优化建议阅读:Pat Burns 的 The R Inferno。
  • 我对速度并不在意。我已经运行了一次模拟,所花费的时间是合理的。我有兴趣保留 rle 数据并将其容纳在我已经工作的代码中。
  • 我可能会帮助您展示您期望看到的返回内容。无论如何,为什么不拥有两个向量 lengthsvalues 并附加每个向量,而不是尝试附加两个向量的复杂列表。我会分配存储而不是追加,但如果你不关心效率,你可以处理它。我确实想知道是否有足够的空间将这些数据存储在内存中。如果您只需要表格摘要,则存储所有信息是一种浪费。
  • 针对您对问题的第二次修改:在我的回答中,我展示了如果您从一个因子中采样,如何强制rle 始终具有相同的长度。只要你清楚地指出问题所在,R 中的一切都很容易。
  • -1(我投了反对票)这个问题很不清楚当时想要什么。它正在变得更好,但我仍然不得不从 cmets 和更新的踪迹中推断出想要的东西。一些预期的输出怎么样!如果您表明我们可以消除歧义,我可以删除反对票。

标签: r loops append coin-flipping


【解决方案1】:

您需要阅读 rle 的帮助页面。考虑:

names(rlex)  #"lengths"  "values"  "lengths"  "values" .... and so on

与此同时,我强烈建议您花一些时间阅读统计方法。运行一百万次二项式模拟的可能性为零(+/- epsilon),它会告诉您经过数百次尝试后您不会学到的任何东西,除非您的硬币有 p=1e-5 :-)。

【讨论】:

    【解决方案2】:

    好的,尝试第 4 次:

    N <- 5
    set.seed(1)
    x <- NULL
    for (i in 1:N){
      x <- rbind(x, table(rle(sample(0:1, 100000, replace=TRUE))))
    }
    
    x <- as.data.frame(x)
    x$length <- as.numeric(rownames(x))
    aggregate(x[, 1:2], list(x[[3]]), sum)
    

    生产:

       Group.1     0     1
    1        1 62634 62531
    2        2 31410 31577
    3        3 15748 15488
    4        4  7604  7876
    5        5  3912  3845
    6        6  1968  1951
    7        7   979   971
    8        8   498   477
    9        9   227   246
    10      10   109   128
    11      11    65    59
    12      12    24    30
    13      13    21    11
    14      14     7    10
    15      15     0     4
    16      16     4     2
    17      17     0     1
    18      18     0     1
    

    如果您想在循环内进行聚合,请执行以下操作:

    N <- 5
    set.seed(1)
    x <- NULL
    for (i in 1:N){
      x <- rbind(x, table(rle(sample(0:1, 100000, replace=TRUE))))
      y <- aggregate(x, list(as.numeric(rownames(x))), sum)
      print(y)
    }
    

    【讨论】:

    • 虽然我确信这可以正常工作,但我不能在我的(更复杂的)代码中使用它。我将不得不解决数千个单独的表(我将不得不手动组合),或者按照问题中的说明找到解决我的问题的方法。不过还是谢谢。
    • @RSoul 我已经按照说明回答了您的问题。您现在正在施加额外的限制,尽管您没有说明它们是什么。
    • @RSoul 由于您修改了问题以强制循环,因此我编辑了答案。
    • 唯一明显的是,在 R 中几乎从不需要循环。如果您对没有得到想要的响应感到沮丧,也许是因为您的问题含糊不清?我们试图提供帮助,但我们都没有水晶球。此外,如果 OP 不是刻薄的,我们发现提供帮助会容易得多,并且您的一些 cmets 已经接近于刻薄的范围。
    • 我想知道你们两个是不是有交叉的目的? OP 不想要 0 或 1 的数量,而是运行长度数据;即$lengths。即便如此,他们似乎只关心摘要而不关心实际数据。 @RSoul,如果超过 4 个 SO 用户无法理解您想要什么,我确实想知道为什么您似乎认为我们没有得到您想要的东西是我们的错,而不是您需要的更简单的假设解释向我们展示您想要更好的东西。我确实要求提供预期的输出,但您没有将其编辑到您的问题中,这将有助于消除歧义。
    【解决方案3】:

    跟进@CarlWitthoft 的回答,您可能想要:

    N <- 5
    rlex <-NULL
    for (i in 1:N) {
        x <-sample(0:1, 100000, 1/2)
        rlex <-append(rlex, rle(x)$lengths)
    }
    

    因为我认为您不关心 $values 组件(即每次运行是零还是一)。

    结果:一个长的游程向量。

    但这可能会更有效率:

    maxlen <- 30
    rlemat <- matrix(nrow=N,ncol=maxlen)
    for (i in 1:N) { 
        x <-sample(0:1, 100000, 1/2)
        rlemat[i,] <- table(factor(rle(x)$lengths,levels=1:maxlen))
    }
    

    结果N by maxlen 每次迭代的运行长度表。

    如果您只想保存每个长度的总运行次数,您可以尝试:

    rlecumsum <- rep(0,maxlen)
    for (i in 1:N) { 
        x <-sample(0:1, 100000, 1/2)
        rlecumsum <- rlecumsum + table(factor(rle(x)$lengths,levels=1:maxlen))
    }
    

    结果:长度为 maxlen 的向量,占所有迭代的总运行长度。

    这是我的最终答案:

    rlecumtab <- matrix(0,ncol=2,nrow=maxlen)
    for (i in 1:N) { 
       x <- sample(0:1, 100000, 1/2)
       r1 <- rle(x)
       rtab <- table(factor(r1$lengths,levels=1:maxlen),r1$values)
       rlecumtab <- rlecumtab + rtab
    }
    

    结果maxlen 除以所有迭代的运行长度总数的 2 表,除以类型(0 次运行与 1 次运行)。

    【讨论】:

    • 其实这已经是我所知道的了。我认为这将保留太多数据。我真的只需要 table(rle(x)) 的输出,在每个循环之后合并。如果这很清楚(似乎不是)。不过还是谢谢。
    • “合并”是指您只想保留每个长度的总运行次数吗?您可以使用colSums(rlemat) 将矩阵折叠为总计,您可以在每个循环迭代中设置rlecumsum &lt;- rep(0,maxlen),然后设置rlecumsum &lt;- rlecumsum + table(...) ...
    • 合并意味着每个循环。总体上,长度为 1、2、3、4 的运行次数合并为一个总数。真的那么不清楚吗?
    • 嗯,是的,它是:“合并”是相当模糊的,因为该术语还意味着将多个表的列组合成一个表......显示所需的输出您在问题中的示例是消除歧义的好方法。
    • 但您还没有告诉我们“合并/合并/将两个表合并到 ubertable”是什么意思。我在上面给出了三个答案,我仍然不知道其中任何一个是否真的是你想要的。如果您显示所需的输出,那么如果它提供所需的输出,那么任何答案都是清晰明确的正确。我的最后一个答案是你想要的吗?您想保留每次运行的结果,还是只保留总数?您是想将“0 次运行”和“1 次运行”长度分布分开,还是只对整体运行长度分布感兴趣?
    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 2015-07-11
    • 1970-01-01
    • 2019-11-09
    • 2018-10-04
    • 2014-05-08
    • 1970-01-01
    • 2017-08-24
    相关资源
    最近更新 更多