【问题标题】:change variable values based on preceding value根据前一个值更改变量值
【发布时间】:2016-11-01 02:33:50
【问题描述】:

我有以下数据集:

df <- data.frame(subject = c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3), 
             time = c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11), 
             performance = c(1,0,-1,-1,0,1,1,-1,0,0,0,1,1,1,-1,0,1,1,-1,0,0,1,-1,1,1,0,1,1,-1,0,-1,-1,0))

我想做的是更改性能变量中的一些条目。更具体地说,如果“-1”条目前面有“1”,我想将“-1”更改为“0”。

但是,这应该只在科目内完成,而不是跨科目(所有科目都有不同数量的会话)。

所以,这就是我最终想要的:

 df2 =data.frame(subject = c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3), 
                        time = c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11), 
                        performance = c(1,0,-1,-1,0,1,1,0,0,0,0,1,1,1,0,0,1,1,0,0,0,1,-1,1,1,0,1,1,-1,0,-1,-1,0))

有人知道怎么做吗?

提前致谢! S.

【问题讨论】:

    标签: r replace conditional


    【解决方案1】:

    使用by 和sapply 的基本R 解决方案:

    gr <- do.call(c, by(df, df$subject, function(x) {
    c(FALSE, unlist(sapply(1:length(x$performance), 
    function(y) (x$performance[y] == -1) & (x$performance[y-1] == 1))))
    }))
    df[gr, 3] <- 0
    cbind(df, df2)
    

    【讨论】:

      【解决方案2】:

      这是一种 data.table 方法,我首先创建一个 flag 列,然后用于对数据进行子集化并通过引用更新 performance 列。

      library(data.table)
      dt <- as.data.table(df) # or setDT(df)
      dt[, flag := performance == -1 & shift(performance, 1L) == 1, by = subject]
      dt[(flag), performance := 0][, flag := NULL]
      

      我选择使用中间标志列,因为我希望它在大型数据集上表现得非常好。如果您不关心性能,您当然可以改用ifelse 或replace。

      【讨论】:

      • 值 29 是否也得到 0?
      • 对,29 应该是 0 - 抱歉!感谢您的帮助!
      【解决方案3】:

      这很难看,但应该可以:

      dftest <- df
      for (i in 2:nrow(dftest)) {
        if(
          dftest$performance[i] == -1 && dftest$performance[i - 1] == 1
        ){
          if(
            dftest$subject[i] == dftest$subject[i - 1]
          ) {
            dftest$performance[i] <- 0
          }
       }
      }
      
      all.equal(df2, dftest) # ONE ERROR
      

      这在第 29 行给出了一个错误 - 你能在这里检查你的示例 df2 是否正确吗?如果我正确理解问题df2$performance[29] 应该是0?

      【讨论】:

      • 我相信这在订购df$subject 时是最合适的。请注意,在 R 中,您可以避免循环,因为所有关系操作都对“向量”进行操作。 IE。以上转化为更高效的df$performance[c(FALSE, df$subject[-1] == df$subject[-nrow(df)]) &amp; c(FALSE, (df$performance[-nrow(df)] == 1L) &amp; (df$performance[-1] == -1L))] = 0
      • 是的,没有考虑无序的情况。至于循环 - 是的,我个人最喜欢 dplyr 解决方案,我只是有点习惯使用循环......
      • 对,第 29 行应该是 0!感谢您的帮助!
      【解决方案4】:

      使用dplyr,

      df %>% 
        group_by(subject) %>% 
        mutate(performance = replace(performance, which(performance + lag(performance)==0 & performance == -1), 0))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-29
        • 2020-01-02
        • 2020-02-18
        • 1970-01-01
        • 2021-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多