R:计算条件在数据框中出现的次数

R: Counting the Number of Times a Condition Appears in a Data Frame

提问人:stats_noob 提问时间:11/22/2021 最后编辑:stats_noob 更新时间:11/23/2021 访问量:238

问:

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

  • 假设有一枚硬币有 5% 的几率落在正面,95% 的几率落在反面

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

  • 观察 HEADS, TAILS, HEADS 之前的最小翻转次数

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

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

我试图用 R 编写一个模拟,将这枚硬币翻转三次,我称之为“运行”。然后,模拟执行 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")

enter image description here

但是有人可以帮我格式化/修改我的代码以简化我想要实现的目标吗?目前,我使用以下 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 循环 for 循环 数据操作

评论


答:

2赞 Wimpel 11/22/2021 #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

评论

0赞 stats_noob 11/23/2021
@Wimpel :谢谢你的回答!您的 R 代码使用了我没有研究过的函数!我能问你一些关于他们的问题吗?
3赞 Isa 11/22/2021 #2

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

for 循环将运行您想要重复测试的次数,而 while 循环将帮助您在第一次 H T H 组合发生时停止测试。

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

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

评论

0赞 stats_noob 11/23/2021
@赛义德:谢谢你的回答!为什么需要粘贴/折叠线?你为什么不写:for (j in 1:100) 和 for (i in 1:100)?谢谢!
0赞 Isa 11/23/2021
欢迎!例如,需要粘贴和折叠才能将字符串组合成一个字符串。<- c('X', 'Y', 'Z') 是一个向量,paste(A) 将返回 “X” “Y” “Z”,而 paste(A, collapse = '') 将返回一个字符串为“XYZ”,这是一种更好的比较方式。此外,对于在 for 循环中迭代,我使用了 j,因为我已经在 while 循环中使用了
2赞 Arjun Paudel 11/23/2021 #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 包 (v2.0.1) 于 2021-11-22 创建