【问题标题】:Check for number of consecutive 0's and replace them according to their count检查连续 0 的数量并根据它们的计数替换它们
【发布时间】:2020-04-23 16:42:20
【问题描述】:

我有一个数据框,其值如下

df=data.frame(c(0,0,NA),c(0,0,NA),c(0,1,0),c(1,0,0),c(0,0,1),c(1,0,1),c(0,1,0),c(1,0,0),c(1,0,0),c(0,0,1),c(0,0,1))  

0   0   0   1   0   1   0   1   1   0   0   
0   0   1   0   0   0   1   0   0   0   0   
NA  NA  0   0   1   1   0   0   0   1   1

我必须计算连续 0 的数量。第一个 0 必须转换为 .95
如果有 2 个连续的 0,则第二个必须转换为 .6
如果有 3 个或更多连续的 0,则必须将它们转换为 .4
如果值为 1,则应不理会它。
在显示的示例中,数据框将转换为:

0.95  0.6   0.4   1     0.95  1     0.95  1     1     0.95  0.6  
0.95  0.6   1    0.95   0.6   0.4   1     0.95  0.6   0.4   0.4
NA    NA   0.95  0.6    1     1     0.95  0.6   0.4   1     1

这只能使用基本包来完成。

【问题讨论】:

  • 您可以发布您的数据框的dput 吗?不清楚这是一个具有 1 列和 2 行的数据框,其中值是 1 和 0 的字符串,还是 12 列和 2 行...
  • @AntoniosK 有 12 列和 2 行。我创建了一个示例数据框。使用这个 df=data.frame(c(0,0),c(0,0),c(0,1),c(1,0),c(0,0),c (1,0),c(0,1),c(1,0),c(1,0),c(0,0),c(0,0))

标签: r dataframe


【解决方案1】:

你可以试试:

conditions <- data.frame(cond = c(0, 1, 2, 3), vals = c(1, .95, .6, .4))

transp <- as.data.frame(t(df))

transp[] <- lapply(transp, 
                   function(x) 
                     ave(x, 
                         !is.na(x), 
                         FUN = 
                           function(i) conditions[, 2][
                             match(ave(i, cumsum(i != 0), FUN = function(y) pmin(cumsum(y == 0), 3)), conditions[, 1])
                             ]))

t(transp)

输出:

    c.0..0..NA. c.0..0..NA..1 c.0..1..0. c.1..0..0. c.0..0..1. c.1..0..1. c.0..1..0..1 c.1..0..0..1 c.1..0..0..2 c.0..0..1..1 c.0..0..1..2
V1        0.95           0.6       0.40       1.00       0.95        1.0         0.95         1.00          1.0         0.95          0.6
V2        0.95           0.6       1.00       0.95       0.60        0.4         1.00         0.95          0.6         0.40          0.4
V3          NA            NA       0.95       0.60       1.00        1.0         0.95         0.60          0.4         1.00          1.0

【讨论】:

  • 您能否详细说明您在 FUN 部分所做的工作,即 pmin(cumsum(y == 0), 3)), conditions[, 1])?
  • 这为每个零分配一个连续的数字,即第一个零得到 1,第二个 2,第三个 3,pmin 确保如果有更多连续的零都将计为 3,这样我们不需要扩展 conditions 数据框并将它们全部视为 3(需要 .4 作为替换)。 conditions[, 1] 实际上在 FUN 部分之外,它只是尝试将计算与 0、1、2 或 3 匹配。
  • 如果数据中有 NA,你能做到吗?这是一个示例数据框 df=data.frame(c(0,0,NA),c(0,0,NA), c(0,1,0),c(1,0,0),c(0,0,1),c(1,0,1),c(0,1,0),c(1,0 ,0),c(1,0,0),c(0,0,1),c(0,0,1)) 您的原始建议在此数据帧上没有给出正确的输出。你能提出一个解决方案吗
  • 我不知道什么是正确的输出。请更新问题
  • 编辑了问题,您的解决方案在前 2 行中工作正常。但是在第三行中,所有 0 都转换为 1,所有 1 都转换为 .95
【解决方案2】:

一个非常丑陋的解决方案可能是:

dt <- data.frame(c(0,0),c(0,0),c(0,1),c(1,0),c(0,0),c(1,0),c(0,1),c(1,0),c(1,0),c(0,0),c(0,0)) 


for (i in 1:dim(dt)[1]) { 
  count <- 0
  for (j in 1:dim(dt)[2]) {
    if (dt[i,j] == 0) {
      if (count == 0) dt[i,j] <- 0.95
      if (count == 1) dt[i,j] <- 0.6
      if (count >= 2) dt[i,j] <- 0.4
      count <- count + 1
    } else { count <- 0 }
  }
}

【讨论】:

    【解决方案3】:

    另一种选择:

    df = data.frame(c(0,0),c(0,0),c(0,1),c(1,0),c(0,0),c(1,0),c(0,1),c(1,0),c(1,0),c(0,0),c(0,0)) 
    
    y <- c(0.95, 0.6, rep(0.4, ncol(df) - 2))
    t(apply(df, 1L, function(x) {
        with(rle(x), {
            unlist(mapply(function(v, l) if(!is.na(v) && v==0L) y[seq.int(l)] else rep(v, l), values, lengths))
        })
    }))
    

    输出:

         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
    [1,] 0.95  0.6 0.40 1.00 0.95  1.0 0.95 1.00  1.0  0.95   0.6
    [2,] 0.95  0.6 1.00 0.95 0.60  0.4 1.00 0.95  0.6  0.40   0.4
    [3,]   NA   NA 0.95 0.60 1.00  1.0 0.95 0.60  0.4  1.00   1.0
    

    【讨论】:

      猜你喜欢
      • 2021-11-17
      • 2021-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 2017-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多