Заменить NA на основе ценностей, окружающих их - PullRequest
1 голос
/ 15 мая 2019

Допустим, у меня есть вектор, заполненный NA с, за исключением каждого 5-го значения, которое может быть одним из двух уровней:

RNGkind('Mersenne-Twister')
set.seed(42)

x <- NULL
for(i in 1:1000){
  x <- c(x,c(sample(c('Hey', 'Hullo'), 1, rep = F), rep(NA, 4)))
}
x

Я хочу заполнить NA сосновываясь на том, что их окружает:

"Hullo" NA NA NA NA "Hey": NAs become "Hey" 
"Hullo" NA NA NA NA "Hullo" NAs become "Hullo"
"Hey" NA NA NA NA "Hullo": NAs become "Hullo"
"Hey" NA NA NA NA "Hey": NAs become "Hey"

Я придумал цикл for, который просматривает каждый элемент итеративно и заполняет NA s, основываясь на множестве операторов if:

for(i in 1:length(x)){
  if(!is.na(x[i])){
     next
   }else{
    if(x[i-1] == 'Hullo' & x[i+4] == 'Hullo' | x[i-1] == 'Hey' & x[i+4] == 'Hullo'){
      x[i:(i+3)] <- 'Hullo'
    }else{
      x[i:(i+3)] <- 'Hey'
    }
  }
}

Но это немного хакерский способ сделать это, и при этом он не касается хвостовой части вектора, где может быть NA.В идеале, последняя группа NA должна соответствовать выходным данным последней группы.

Если это облегчает задачу, всегда будет четыре NA с между двумя не NA с.

Есть ли:

  1. более элегантный / более быстрый способ сделать это?
  2. способ заполнить конец вектора без необходимости делать это вручную?

РЕДАКТИРОВАТЬ: Добавлено то, что будет последней группой NA с, и подтвердить, что не NA с всегда происходит всогласованные интервалы (каждый 5-й элемент)

Ответы [ 2 ]

2 голосов
/ 15 мая 2019

Вот решение с использованием пакета tidyr:

xres <- tidyr::fill(data = data.frame(x, stringsAsFactors = FALSE), x, .direction = "up")
xres <- tidyr::fill(data = xres, x, .direction = "down")
xres$x

Сначала вы заполняете одно направление, а затем заполняете другое, чтобы получить последние значения

0 голосов
/ 15 мая 2019

Если я хорошо понял ваш вопрос, я пытаюсь ответить, используя подход tidyverse.

Загрузить библиотеку:

library(tidyverse)

Загрузите ваши данные:

var1 <- c("Hullo",NA,NA,NA,NA,"Hey")
var2 <- c("Hullo",NA,NA,NA,NA,"Hullo")
var3 <- c("Hey",NA,NA,NA,NA,"Hullo")
var4 <- c("Hey",NA,NA,NA,NA,"Hey")

my_df <- as.data.frame(cbind(var1,var2,var3,var4))

Затем используйте функцию fill:

my_df %>% 
    fill(... = var1:var4,.direction = "up")

это результат:

   var1  var2  var3 var4
1 Hullo Hullo   Hey  Hey
2   Hey Hullo Hullo  Hey
3   Hey Hullo Hullo  Hey
4   Hey Hullo Hullo  Hey
5   Hey Hullo Hullo  Hey
6   Hey Hullo Hullo  Hey
...