【问题标题】:Split vector by a first appearance of another vector通过另一个向量的第一次出现来分割向量
【发布时间】:2020-09-29 10:01:51
【问题描述】:

我有以下数据:

   players trial choice
1        1     1      0
2        1     2      1
3        1     3      0
4        1     4      0
5        1     5      0
6        2     1      0
7        2     2      0
8        2     3      1
9        2     4      0
10       2     5      1

现在我想根据选择中“1”的第一个外观创建另一个向量(“拆分数据”) 每个玩家:

     players trial choice new_vec
1        1     1      0       1
2        1     2      1       1
3        1     3      0       0
4        1     4      0       0
5        1     5      0       0
6        2     1      0       1
7        2     2      0       1
8        2     3      1       1
9        2     4      0       0
10       2     5      1       0

所以对于每个玩家,在第一个“1”选择之前,新向量得到“1”,之后是“0”。

有什么办法吗?

【问题讨论】:

    标签: r dataframe split


    【解决方案1】:

    我们可以使用match 来获取choice 中第一个出现的1,并为每个player 分配低于该值的行号为1。

    library(dplyr)
    df %>%
      group_by(players) %>%
      mutate(new_vec = +(row_number() <= match(1, choice)))
      #We can also use `which.max
      #mutate(new_vec = +(row_number() <= which.max(choice)))
    
    #  players trial choice new_vec
    #     <int> <int>  <int>   <int>
    # 1       1     1      0       1
    # 2       1     2      1       1
    # 3       1     3      0       0
    # 4       1     4      0       0
    # 5       1     5      0       0
    # 6       2     1      0       1
    # 7       2     2      0       1
    # 8       2     3      1       1
    # 9       2     4      0       0
    #10       2     5      1       0
    

    同样的逻辑可以在data.table中实现:

    library(data.table)
    setDT(df)[, new_vec := +(seq_len(.N) <= match(1, choice)), players]
    

    和基础R:

    df$new_vec <- with(df, ave(choice, players, FUN = function(x) seq_along(x) <= match(1, x)))
    

    【讨论】:

      【解决方案2】:

      使用ave。

      dat <- transform(dat, new_vec=ave(choice, players, FUN=function(x) 
        if (x[1] == 1) 1 else +!c(F, (cumsum(x) > 0)[-length(x)])))
      dat
      #    players trial choice new_vec
      # 1        1     1      0       1
      # 2        1     2      1       1
      # 3        1     3      0       0
      # 4        1     4      0       0
      # 5        1     5      0       0
      # 6        2     1      0       1
      # 7        2     2      0       1
      # 8        2     3      1       1
      # 9        2     4      0       0
      # 10       2     5      1       0
      

      数据:

      dat <- tructure(list(players = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
      2L), trial = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L), choice = c(0L, 
      1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L)), class = "data.frame", row.names = c("1", 
      "2", "3", "4", "5", "6", "7", "8", "9", "10"))
      

      【讨论】:

        【解决方案3】:

        另一个ave()解决方案:

        df$new_vec <-
          ave(x = df$choice, df$players, FUN = function(x) cummax(c(0, head(x, -1))) == 0)
        

        在data.table:

        setDT(df)
        df[, new_vec := as.integer(cummax(shift(choice, fill = 0)) == 0), by = players]
        

        可重复的数据

        df <- data.frame(
          players = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), 
          trial = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L), 
          choice = c(0L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L)
        )
        

        【讨论】:

          猜你喜欢
          • 2021-03-06
          • 2015-07-19
          • 1970-01-01
          • 2020-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-09
          • 1970-01-01
          相关资源
          最近更新 更多