Проверьте количество последовательных 0 и замените их в соответствии с их количеством - PullRequest
1 голос
/ 23 апреля 2020

У меня есть фрейм данных со значениями, такими как следующие

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

Это должно быть сделано с помощью только базовый пакет.

Ответы [ 3 ]

2 голосов
/ 23 апреля 2020

Вы можете попробовать:

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
2 голосов
/ 24 апреля 2020

Другой вариант:

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
2 голосов
/ 23 апреля 2020

Очень уродливое решение может быть:

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 }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...