【问题标题】:Assigning probability for sample() within tapply()在 tapply() 中为 sample() 分配概率
【发布时间】:2020-02-02 00:58:08
【问题描述】:

使用以下内容:

name<-c(rep("Adam", times = 6), rep("Barry", times = 4), rep("Charlie", times = 5))
group<-c(1:15)
probs<-c(0.4, 0.2, 0.1, 0.15, 0.1, 0.05, 0.25, 0.35, 0.3, 0.1, 0.2, 0.15, 0.30, 0.15, 0.2)
df<-data.frame(name, group, probs)

我正在尝试创建一个输出,该输出采用每个 $name 并根据 $probs 中的概率为其分配一个 $group。例如,Adam 有 40% 的机会在第 1 组,20% 的机会在第 2 组,10% 的机会在第 3 组,等等。

最终结果将根据这些概率为每个名称返回一组,并且看起来像这样

   Adam   Barry Charlie 
      5      10      12 

我相信我应该使用 tapply() 并运行了以下命令,但这并不能解释各种概率

tapply(df$group, df$name, sample, 1)

为了利用各种概率,我也尝试了以下方法,但由于概率数不正确而返回错误

tapply(df$group, df$name, sample, 1, prob = df$probs)

非常感谢任何有关如何解决这些问题并获得所需输出的见解。

【问题讨论】:

    标签: r sample tapply


    【解决方案1】:

    不是tapply() 解决方案,但这是来自dplyrsample_n() 解决方案。

    将您的probs 列重命名为expected_probs

    name<-c(rep("Adam", times = 6), rep("Barry", times = 4), rep("Charlie", times = 5))
    group<-c(1:15)
    expected_probs<-c(0.4, 0.2, 0.1, 0.15, 0.1, 0.05, 0.25, 0.35, 0.3, 0.1, 0.2, 0.15, 0.30, 0.15, 0.2)
    df<-data.frame(name, group, expected_probs)
    
    library(dplyr)
    
    df %>% 
      group_by(name) %>%
      sample_n(size = 1, weight = expected_probs)
    
    # A tibble: 3 x 3
    # Groups:   name [3]
      name    group expected_probs
      <fct>   <int>          <dbl>
    1 Adam        4           0.15
    2 Barry       9           0.3 
    3 Charlie    12           0.15
    

    通过复制样本检查观察结果是否与预期概率匹配:

    iterations <- 10000
    
    results <- replicate(expr = df %>% 
                           group_by(name) %>%
                           sample_n(size = 1, weight = expected_probs),
                         n = iterations,
                         simplify = FALSE) %>% 
      bind_rows(.id = "iteration") %>% 
      group_by(name, group, expected_probs) %>% 
      summarize(observed_probs = n() / iterations)
    
    results
    
    # A tibble: 15 x 4
    # Groups:   name, group [15]
       name    group expected_probs observed_probs
       <fct>   <int>          <dbl>          <dbl>
     1 Adam        1           0.4          0.391 
     2 Adam        2           0.2          0.198 
     3 Adam        3           0.1          0.102 
     4 Adam        4           0.15         0.154 
     5 Adam        5           0.1          0.104 
     6 Adam        6           0.05         0.0504
     7 Barry       7           0.25         0.252 
     8 Barry       8           0.35         0.346 
     9 Barry       9           0.3          0.297 
    10 Barry      10           0.1          0.105 
    11 Charlie    11           0.2          0.202 
    12 Charlie    12           0.15         0.151 
    13 Charlie    13           0.3          0.294 
    14 Charlie    14           0.15         0.153 
    15 Charlie    15           0.2          0.201 
    

    【讨论】:

      【解决方案2】:

      tapply 只能接受一个向量,所以你需要做类似的事情:

      by(df,df$name,function(i)sample(i$group,1,prob=i$probs))
      

      但是输出不是很好,

      df$name: Adam
      [1] 2
      ------------------------------------------------------------ 
      df$name: Barry
      [1] 8
      ------------------------------------------------------------ 
      df$name: Charlie
      [1] 12
      

      【讨论】:

        【解决方案3】:

        这是一个不使用tapply,但使用splitsapply 的基本R 解决方案。我们将抽取样本两次。使用 set.seed(42) 保证你在这里得到相同的结果。运行自己的数据时不需要使用它:

        set.seed(42)
        grps <- split(df, df$name)
        sapply(grps, function(x) sample(x$group, 1, prob=x$expected_probs))
        #    Adam   Barry Charlie 
        #       5      10      13 
        # sapply(grps, function(x) sample(x$group, 1, prob=x$expected_probs))
        #    Adam   Barry Charlie 
        #      3       9      11 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-25
          • 1970-01-01
          • 1970-01-01
          • 2014-09-09
          • 2017-06-13
          相关资源
          最近更新 更多