Заменить НС путем имитации данных
В векторе, содержащем блоки чисел и блоки NA, такие как:
score <- c(0,1,2,3,4,NA,NA,0,-1,0,1,2,NA,NA,NA)
Есть ли способ имитировать отсутствующие значения путем подсчета вверх с шагом один от последнего значения до блока NA?
Итак, это будет:
score.correct <- c(0,1,2,3,4,5,6,0,-1,0,1,2,3,4,5)
Спасибо за любую помощь.
Ответы
Ответ 1
Q + D, имеет петлю, делает некоторое ненужное дополнение, но выполняет задание:
incna <- function(s){
while(any(is.na(s))){
ina = which(is.na(s))
s[ina]=s[ina-1]+1
}
s
}
> score
[1] 0 1 2 3 4 NA NA 0 -1 0 1 2 NA NA NA
> incna(score)
[1] 0 1 2 3 4 5 6 0 -1 0 1 2 3 4 5
Сбой только с предупреждением, если первый элемент равен NA:
> score
[1] NA 1 2 3 4 NA NA 0 -1 0 1 2 NA NA NA
> incna(score)
[1] 5 1 2 3 4 5 3 0 -1 0 1 2 3 4 5
Warning message:
In s[ina] = s[ina - 1] + 1 :
number of items to replace is not a multiple of replacement length
Ответ 2
Адаптировано из Christos Hatzis on r-help:
rna <- function(z) {
y <- c(NA, head(z, -1))
z <- ifelse(is.na(z), y+1, z)
if (any(is.na(z))) Recall(z) else z }
rna(score)
#[1] 0 1 2 3 4 5 6 0 -1 0 1 2 3 4 5
Драконы:
rna(c(NA,score))
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
rna(c(1,rep(NA,1e4)))
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
Benchmark:
score2 <- 1:1e5
set.seed(42)
score2[sample(score2,10000)] <- NA
library(microbenchmark)
microbenchmark(rna(score2),incna(score2))
Unit: milliseconds
expr min lq median uq max
1 incna(score2) 2.93309 2.973896 2.990988 3.134501 5.360186
2 rna(score2) 50.42240 50.848931 51.228040 52.778043 56.856773
Ответ 3
Вот еще один подход:
library(zoo)
ifelse(is.na(score), na.locf(score) + sequence(rle(is.na(score))$l), score)
# [1] 0 1 2 3 4 5 6 0 -1 0 1 2 3 4 5
Отображение промежуточных результатов с помощью []
с указанием слотов NA
:
na.locf(score)
# [1] 0 1 2 3 4 [4] [4] 0 -1 0 1 2 [2] [2] [2]
sequence(rle(is.na(score))$l)
# [1] 1 2 3 4 5 [1] [2] 1 2 3 4 5 [1] [2] [3]
na.locf(score) + sequence(rle(is.na(score))$l)
# [1] 1 3 5 7 9 [5] [6] 1 1 3 5 7 [3] [4] [5]
ifelse(is.na(score), na.locf(score) + sequence(rle(is.na(score))$l), score)
# [1] 0 1 2 3 4 [5] [6] 0 -1 0 1 2 [3] [4] [5]