根据分组数据框中的先前值确定结果

时间:2018-07-27 09:31:08

标签: r dplyr tidyverse

我有一个具有以下格式的数据框:

pair group group_rank win_prob
<int> <int>   <chr>    <dbl>
 1     1      first     0.6
 1     2      second    0.4
 2     3      first     0.5
 2     4      second    0.5

它是用以下代码段生成的:

library(tidyverse)

df <- tibble(pair = rep(c("A", "B"), each = 2),
            group = seq(1:4),
            group_rank = c("first", "second", "first", "second"),
            win_prob = c(0.6, 0.4, 0.5, 0.5))

我的目标是将“获胜”分配给每对中的一组,将“损失”分配给 另一组。换句话说,我想产生以下 具有新列结果的数据框:

pair group group_rank win_prob outcome
<int> <int>    <chr>      <dbl> <chr>  
  1     1     first       0.6   win    
  1     2     second      0.4   loss   
  2     3     first       0.5   loss   
  2     4     second      0.5   win

应将“赢”或“亏损”分配给结果变量 基于group_rank和win_prob中的相应值 变量。更具体地说,每次我想先检查是否 通过检查是否具有group_rank ==“ first”的组获胜 其win_prob> = runif(1)(伯努利径)。

如果条件满足,我想为此分配“胜利” 组。如果不满足条件,我要分配“损失”。

在确定group_rank ==“ first”的组是否具有 胜负,我想将相反的结果分配给 group_rank ==“第二”。因此,如果“第一”组已经 分配“胜利”,第二组应该分配“损失”, 反之亦然。

在伪代码中,应该是这样,但是窍门是如何在分组的数据框中查找“第一”组的结果,同时确定“第二”组的结果:

for pair in pairs: 
    if group_rank == ``first'' and win_prob >= runif(1):
        outcome <- ``win''
    else:
        outcome <- ``loss''

    if group_rank == ``second'':
        if outcome == ``win'' for group with group_rank == ``first'':
            outcome <- ``loss''
        else:
            outcome <- ``win''

在tidyverse框架中是否有一种简单的方法来实现这一目标?

1 个答案:

答案 0 :(得分:2)

使用data.table可以做到这一点:

res <- c("win", "lose") # Not a good name but this is one of two possible results.
setDT(df)[, 
          outcome := {
            temp = win_prob[1] >= runif(1); 
            ifelse(c(temp, temp), res, rev(res))
          }, 
          by = pair]
df
   pair group group_rank win_prob outcome
1:    A     1      first      0.6     win
2:    A     2     second      0.4    lose
3:    B     3      first      0.5    lose
4:    B     4     second      0.5     win

使用dplyr

df %>%
  group_by(pair) %>%
  mutate(temp = win_prob[1] >= runif(1)) %>%
  mutate(outcome = ifelse(temp, res, rev(res))) %>%
  select(-temp)

注意:
两种解决方案都假设数据已经排序,因此对于每对数据,group_rank first始终显示在上方。