【问题标题】:R: Counting the Number of Times a Condition Appears in a Data FrameR:计算条件在数据框中出现的次数
【发布时间】:2021-12-31 17:55:51
【问题描述】:

我正在使用 R 编程语言。我想到了以下我想测试的问题:

  • 假设有一枚硬币有 5% 的机会正面朝上,95% 的机会朝反面着陆

基于计算机模拟,我想找出以下内容:

  • 观察HEADS、TAILS、HEADS前的最少翻转次数

  • 观察HEADS、TAILS、HEADS前的平均翻转次数

  • 观察HEADS、TAILS、HEADS前的最大翻转次数

我尝试在 R 中编写一个模拟,将这枚硬币翻转 3 次,我称之为“运行”。然后模拟执行 100 次“运行”:

results <- list()

for (i in 1:100){

response_i <- c("H","T")
response_i <- sample(response_i, 3, replace=TRUE, 
                        prob=c(0.05, 0.95))
response_i <- as.factor(response_i)

iteration_i = i

run_i = data.frame(response_i, iteration_i)

 results[[i]] <- run_i

}

这看起来如下(例如运行#22、#23、#24):

[[22]]
  response_i iteration_i
1          T          22
2          T          22
3          T          22

[[23]]
  response_i iteration_i
1          H          23
2          T          23
3          T          23

[[24]]
  response_i iteration_i
1          T          24
2          T          24
3          T          24

我的问题:

我想修改上面的代码,这样:

1) 看到第一个 H、T、H 后模拟自动停止(现在,我运行了 100 次模拟,希望这足以观察至少一个 H , T, T)

2) 一旦第一个 H、T、H 出现并且模拟自动停止,我想记录发生在哪个“运行”(即“iteration_i”的值是多少?)

3)然后我想将整个模拟重复 100 次(100 次运行 * 100 次 = 10,000 次抛硬币)

一旦完成,我将能够制作直方图,显示在观察到 H、T、H 之前的最少掷硬币次数、平均掷硬币次数和最大掷硬币次数(使用“ggplot2” ,我认为这不会太难)。

#sample data
number_of_runs_before_HTH_appeared = c(15,10, 11, 8, 12, 21, 32, 7, 9, 20, 22, 3, 16, 7 )

hist(number_of_runs_before_HTH_appeared, main = "Number of Runs before HTH")

但是有人可以帮我格式化/修改我的代码以简化我想要实现的目标吗?目前,我使用以下 R 代码“整理”了第一次模拟的 100 次“运行”:

results_df <- do.call(rbind.data.frame, results)

 head(results_df)
  response_i iteration_i
1          T           1
2          T           1
3          T           1
4          T           2
5          T           2
6          T           2

然后我手动重复了很多次,例如..g

results_df_1 <- do.call(rbind.data.frame, results)
results_df_1$index = 1

#re-run original simulation
results_df_2<- do.call(rbind.data.frame, results)
results_df_2$index = 2

#re-run original simulation (many times)
results_df_n<- do.call(rbind.data.frame, results)
results_df_n$index = n

final <- data.frame(results_df_1, results_df_2, results_df_n)

然后我将此“最终”文件导入 Microsoft Excel 并尝试手动折叠“最终文件”以回答我的三个原始问题 - 但我希望有人可以通过修改我的原始代码来告诉我如何做到这一点R.

有人可以帮我解决这个问题吗?

谢谢!

【问题讨论】:

    标签: r loops for-loop data-manipulation


    【解决方案1】:

    这可能会让你开始

    library(data.table)
    n <- 100
    simulations <- 100
    # build data.table with simulations
    DT <- data.table(sim = rep(1:simulations, each = n),
                     step = 1:n,
                     flip = lapply(
                       lapply(seq.int(n * simulations), 
                              function(x) sample(c("H","T"), 3, replace=TRUE, prob=c(0.05, 0.95))),
                       paste0, collapse = ""))
    #        sim step flip
    #     1:   1    1  TTT
    #     2:   1    2  TTT
    #     3:   1    3  TTT
    #     4:   1    4  TTT
    #     5:   1    5  TTT
    #    ---              
    #  9996: 100   96  THT
    #  9997: 100   97  TTT
    #  9998: 100   98  TTT
    #  9999: 100   99  TTT
    # 10000: 100  100  TTT
    
    DT
    # find the first step where flip == "HTH" for each sim
    DT[flip == "HTH", .(first_hth = min(step)), by = .(sim)]
    #     sim first_hth
    #  1:   2        88
    #  2:   6        30
    #  3:   7        16
    #  4:  19        38
    #  5:  26        42
    #  6:  28        91
    #  7:  34        87
    #  8:  36        96
    #  9:  38        98
    # 10:  45        74
    # 11:  48        93
    # 12:  51        46
    # 13:  53        30
    # 14:  60        70
    # 15:  68        27
    # 16:  69        53
    # 17:  88        35
    # 18:  91        88
    # 19:  94        74
    # 20:  95       100
    # 21:  97        81
    # 22:  98        24
    #     sim first_hth
    

    【讨论】:

    • @Wimpel:谢谢你的回答!你的 R 代码使用了我没有研究过的函数!我能问你一些关于他们的问题吗?
    【解决方案2】:

    for 和 while 循环的组合将达到您的目的。

    for 循环将运行您想要重复测试的次数,while 循环将帮助您当第一个 HTH 组合出现时停止测试。

    以下是您可以使用并继续执行后续步骤的代码。

    results <- list()
    
    for (j in 1:100) {
    
      response_i <- ''
      i <- 1
    
      while (response_i != 'HTH') {
        response_i <- c("H","T")
        response_i <- sample(response_i, 3, replace=TRUE, 
                             prob=c(0.05, 0.95))
        response_i <- paste(response_i, collapse = '')
    
        iteration_i = i
        if (response_i == 'HTH') {
          run_i = data.frame(response_i, iteration_i)
          results[[j]] <- run_i
          }
        i <- i + 1
      }
    }
    
    data <- do.call('rbind', results)
    
    head(data)
    
          response_i iteration_i
    1        HTH        1206
    2        HTH          46
    3        HTH         116
    4        HTH        1633
    5        HTH         889
    6        HTH          43
    

    【讨论】:

    • @Sayed:谢谢你的回答!为什么需要粘贴/折叠线?你为什么不写:for (j in 1:100) 和 for (i in 1:100)?谢谢!
    • 欢迎您!需要粘贴和折叠才能将字符串组合成单个字符串,例如。 A
    【解决方案3】:
    library(tidyverse)
    set.seed(42)
    coin_flip <- crossing(trial = seq_len(1000),
                    flips = 1:1000) %>% 
      mutate(heads = rbinom(n(), 1, .05)) %>% 
      group_by(trial) %>% 
      mutate(second_flip = lead(heads),
             third_flip = lead(heads,2),
             hth = heads & !second_flip & third_flip) %>% 
      summarise(first_hth = which(hth)[1]+2) 
    coin_flip %>% head()
    #> # A tibble: 6 x 2
    #>   trial first_hth
    #>   <int>     <dbl>
    #> 1     1        46
    #> 2     2        31
    #> 3     3       114
    #> 4     4        NA
    #> 5     5       776
    #> 6     6       292
    coin_flip %>% ggplot(aes(first_hth))+
      geom_histogram()
    #> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
    #> Warning: Removed 96 rows containing non-finite values (stat_bin).
    

    reprex package (v2.0.1) 于 2021 年 11 月 22 日创建

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 1970-01-01
      • 2021-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多