【问题标题】:Dynamically update a variable between rows in R/dplyr在 R/dplyr 中的行之间动态更新变量
【发布时间】:2021-12-20 06:06:05
【问题描述】:

我有来自《战舰》游戏的多个游戏的数据。它看起来像这样:

> data.frame(game=c(1,1,1,1,2,2,2,2),
  position=c(2,4,3,1,1,2,3,4),
  hit=c(0,0,1,0,1,0,0,0))

  game position hit
1    1        2   0
2    1        4   0
3    1        3   1
4    1        1   0
5    2        1   1
6    2        2   0
7    2        3   0
8    2        4   0

每一行是玩家的一个动作:位置是平方数,命中表示他们是否击中了一艘船。 我想创建一个额外的行来指示每次移动之前的棋盘状态。它应该看起来像这样:

  game position hit board_state
1    1        2   0 [NA,NA,NA,NA]
2    1        4   0 [NA,0,NA,NA]
3    1        3   1 [NA,0,NA,0]
4    1        1   0 [NA,0,1,0]
5    2        1   1 [NA,NA,NA,NA]
6    2        2   0 [1,NA,NA,NA]
7    2        3   0 [1,0,NA,NA]
8    2        4   0 [1,0,0,NA]

所以棋盘状态会根据上一步的位置和结果进行更新。

我发现这里具有挑战性的是,board_state 在行 r 上的定义取决于它在行 r-1 上的状态,而 lag 在这里没有用,因为它在同一列中。我希望这很清楚。

关于如何实现这一点的任何想法?谢谢!!!

【问题讨论】:

    标签: r dplyr dynamic lag


    【解决方案1】:

    这是一种使用dplyrtidyr 的方法。首先,我添加一个列来跟踪我们在每场比赛中的哪个回合。 (这将有助于我们在后面的步骤中转向宽。)然后我“完成”表格以在每场比赛中的每个位置和每个回合都有一行。然后我们可以向下“填充”并后退一步,以便每个位置都反映其过去的历史。最后,我们可以按游戏和回合分组,并生成一个“board_position”摘要,将每个位置的“命中”值连接起来。

    library(dplyr); library(tidyr)
    df %>%
      group_by(game) %>%
      mutate(turn = row_number()) %>%
      complete(game, position, turn) %>%
      group_by(game, position) %>%
      fill(hit) %>%
      mutate(hit = lag(hit)) %>%
      group_by(game, turn) %>%
      summarize(board_state = paste(hit, collapse = ", "), .groups = "drop")
    

    结果

    # A tibble: 8 × 3
       game  turn board_state   
      <dbl> <int> <chr>         
    1     1     1 NA, NA, NA, NA
    2     1     2 NA, 0, NA, NA 
    3     1     3 NA, 0, NA, 0  
    4     1     4 NA, 0, 1, 0   
    5     2     1 NA, NA, NA, NA
    6     2     2 1, NA, NA, NA 
    7     2     3 1, 0, NA, NA  
    8     2     4 1, 0, 0, NA  
    

    【讨论】:

    • 谢谢乔恩,这太棒了!两个问题:首先,这段代码中什么保证了board state中的第一个条目对应于位置1?其次,是否可以将 board_state 作为列表而不是字符串?
    • 我假设您的完整数据集使用了所有位置,因此complete 步骤将为所有现有位置创建行。如果不是这种情况,您可以将该行编辑为complete(game, position = 1:4, turn) %&gt;%,以明确包含每个游戏和回合的位置 1、2、3、4。 [我稍后会尝试回到“列表”问题。]
    • 我可能在将其应用于我自己的数据集时做错了,或者它可能是我的数据集的实际大小(25 个位置、1000 个游戏和其他列,如 RT 等),但我得到了一条错误消息('r: cannot allocate vector of size 105.7 Mb')。我想知道对于行的 for 循环是否在这里实际上不会更简单?
    【解决方案2】:

    我最终得到了以下解决方案:

    create_board_states <- function(positions,hits) {
      
      board_state = rep(NA,4)
      board_states = c();
      for (p in seq_along(positions)) {
        board_states = c(board_states, paste(board_state,collapse=','));
        board_state[positions[p]]=hits[p];
      }
      
      return(board_states)
    }
    
    df %>% 
      group_by(game) %>% 
      summarise(board_state=create_board_states(position,hit)) %>% 
      mutate(board_state=as.list(strsplit(board_state,',')))
    

    【讨论】:

      猜你喜欢
      • 2021-02-18
      • 1970-01-01
      • 2020-08-13
      • 2017-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-18
      相关资源
      最近更新 更多