2017-02-17 17 views
2

Я хотел бы заменить все последовательные значения NA на строку с нулем, но только если число последовательных NA s меньше, чем парметер maxgap.Как заменить последовательные NA с нулевым значением, заданным максимальным параметром зазора (в R)

Это очень похоже на функцию zoo::na.locf

x = c(NA,1,2,3,NA,NA,5,6,7,NA,NA,NA) 
zoo::na.locf(x, maxgap = 2, na.rm = FALSE) 

дает

[1] Н.А. 1 2 3 3 3 5 6 7 NA NA NA

Есть два вещи, отличные от моей цели: Я тоже хотел бы заменить ведущий NA, и я бы хотел заменить 2 последовательных NA с 0, а не las t не-NA.

Я хотел бы получить

0 1 2 3 0 0 5 6 7 NA NA NA

Как я могу сделать это в R. Могу ли я использовать функции из tidyverse?

+0

Последние три NAs должны остаться NA - спасибо! – Richard

ответ

2

Если y является результатом na.locf линии тогда, если y[i] не NA, но x[i] является NA, то он был заменен так назначить 0 на него. Кроме того, если это ведущее значение NA, которое происходит, когда нижний нижний cumsum(...) равен 0, замените его также.

replace(y, (!is.na(y) & is.na(x)) | cumsum(!is.na(y)) == 0, 0) 
## [1] 0 1 2 3 0 0 5 6 7 NA NA NA 
+0

Как мы можем применить это элегантно к data.frame или tibble в строке за строкой? x = c (NA, 1,2,3, NA, NA, 5,6,7, NA, NA, NA) y = c (NA, 1,2,3, NA, NA, 5,6,7 , NA, NA, NA) d = data.frame (rbind (x, y)) – Richard

+0

Если функция 'f' работает с одним вектором, то:' t (apply (d, 1, f)) 'производит матрицы, в которой каждая строка преобразуется. –

+0

Отлично, это отлично работает в моем приложении! – Richard

1

Мы можем использовать rle сделать это

f1 <- function(vec){ 
    rl <- rle(is.na(vec)) 
    lst <- within.list(rl, { 
       i1 <- seq_along(values)==1 
       i2 <- seq_along(values) != length(values) 
       values[!((lengths==2 & values & i2)| 
         (values & i1))] <- FALSE 

      }) 
    vec[inverse.rle(lst)] <- 0 
    vec 
} 
f1(x) 
#[1] 0 1 2 3 0 0 5 6 7 NA NA NA 
+0

@docendodiscimus Благодарим вас за комментарии. Я читал его неправильно. Исправлено сейчас – akrun

1

Вы можете, например. сделать это:

require(data.table) 
require(dplyr) 

x = c(NA,1,2,3,NA,NA,5,6,7,NA,NA,NA) 

my_replace <- function(x, n, maxgap){ 
    if(is.na(x[1]) && n <= maxgap){ 
    x <- 0 
    } 
    x 
} 

data.frame(x, y=x) %>% 
    group_by(data.table::rleid(x)) %>% 
    mutate(x = my_replace(x, n(), 2), y = my_replace(y, n(), 1)) %>% 
    ungroup() %>% 
    select(x,y) 

Это позволяет установить maxgap столбцам: для й 2 для у 1.

Это приводит к:

# A tibble: 12 × 2 
     x  y 
    <dbl> <dbl> 
1  0  0 
2  1  1 
3  2  2 
4  3  3 
5  0 NA 
6  0 NA 
7  5  5 
8  6  6 
9  7  7 
10 NA NA 
11 NA NA 
12 NA NA