R - 用最多4个先前值替换缺失值

时间:2017-09-27 20:21:03

标签: r

这是具有一些缺失值的向量中的最后观察结果问题的变体。我没有用最后一次非NA观测来填充NA值,而是希望在其前面的4个观测值中填入具有最高值的NA值。如果前面的所有4个观测值也是NA,则应保留NA缺失值。也可以理解,这可以通过数据框/数据表中的组来完成。

示例:

    Original DF:     

    ID Week Value
    a  1    5
    a  2    1   
    a  3    NA  
    a  4    NA  
    a  5    3  
    a  6    4      
    a  7    NA  
    b  1    NA  
    b  2    NA  
    b  3    NA  
    b  4    NA  
    b  5    NA  
    b  6    1  
    b  7    NA

    Output DF:

    ID  Week  Value  
    a   1     5  
    a   2     1  
    a   3     5   
    a   4     5    
    a   5     3  
    a   6     4  
    a   7     4     
    b   1     NA  
    b   2     NA  
    b   3     NA  
    b   4     NA  
    b   5     NA  
    b   6     1  
    b   7     1

2 个答案:

答案 0 :(得分:1)

lag将列移动n步,让您查看以前的值。 pmax是元素最大值,可以为观察的每个集合/行选​​择最高值。

要抽象出4的概念并保持向量化的表现,你可以使用rlang的quasiquotes:http://dplyr.tidyverse.org/articles/programming.html#quasiquotation

起初看起来有点神秘,但非常精确和富有表现力。


df <- readr::read_table(
"    ID Week Value
    a  1    5
    a  2    1   
    a  3    NA  
    a  4    NA  
    a  5    3  
    a  6    4      
    a  7    NA  
    b  1    NA  
    b  2    NA  
    b  3    NA  
    b  4    NA  
    b  5    NA  
    b  6    1  
    b  7    NA")

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
df %>%
  group_by(ID) %>%
  mutate(
    Value = if_else(is.na(Value), pmax(lag(Value, 1), lag(Value, 2), lag(Value, 3), lag(Value, 4), na.rm = TRUE), Value)
  )
#> # A tibble: 14 x 3
#> # Groups:   ID [2]
#>       ID  Week Value
#>    <chr> <int> <int>
#>  1     a     1     5
#>  2     a     2     1
#>  3     a     3     5
#>  4     a     4     5
#>  5     a     5     3
#>  6     a     6     4
#>  7     a     7     4
#>  8     b     1    NA
#>  9     b     2    NA
#> 10     b     3    NA
#> 11     b     4    NA
#> 12     b     5    NA
#> 13     b     6     1
#> 14     b     7     1

# or if you are an rlang ninja
library(purrr)
pmax_lag_n <- function(column, n) {
  column <- enquo(column)
  1:n %>%
    map(~quo(lag(!!column, !!.x))) %>%
    { quo(pmax(!!!., na.rm = TRUE)) }
}

df %>%
  group_by(ID) %>%
  mutate(Value = if_else(is.na(Value), !!pmax_lag_n(Value, 4), Value))
#> # A tibble: 14 x 3
#> # Groups:   ID [2]
#>       ID  Week Value
#>    <chr> <int> <int>
#>  1     a     1     5
#>  2     a     2     1
#>  3     a     3     5
#>  4     a     4     5
#>  5     a     5     3
#>  6     a     6     4
#>  7     a     7     4
#>  8     b     1    NA
#>  9     b     2    NA
#> 10     b     3    NA
#> 11     b     4    NA
#> 12     b     5    NA
#> 13     b     6     1
#> 14     b     7     1

答案 1 :(得分:0)

定义接受向量Max的函数x,如果其所有元素都是NA,则返回NA。否则,如果最后一个值是NA,则返回所有非NA元素的最大值,如果最后一个值不是NA,则返回它。

同样定义na.max在长度为Max的滚动窗口上运行n(由na.max的第二个参数给出 - 默认为5)。

最后使用na.max ValueID应用于ave

library(zoo)

Max <- function(x) {
  last <- tail(x, 1)
  if (all(is.na(x))) NA
  else if (is.na(last)) max(x, na.rm = TRUE)
       else last
}

na.max <- function(x, n = 5) rollapplyr(x, n, Max, partial = TRUE)

transform(DF, Value = ave(Value, ID, FUN = na.max))

,并提供:

   ID Week Value
1   a    1     5
2   a    2     1
3   a    3     5
4   a    4     5
5   a    5     3
6   a    6     4
7   a    7     4
8   b    1    NA
9   b    2    NA
10  b    3    NA
11  b    4    NA
12  b    5    NA
13  b    6     1
14  b    7     1

注意:以可重现的形式输入DF

Lines <- "
ID Week Value
    a  1    5
    a  2    1   
    a  3    NA  
    a  4    NA  
    a  5    3  
    a  6    4      
    a  7    NA  
    b  1    NA  
    b  2    NA  
    b  3    NA  
    b  4    NA  
    b  5    NA  
    b  6    1  
    b  7    NA"
DF <- read.table(text = Lines, header = TRUE)