首页 > 解决方案 > 有条件地逐列替换领先和落后的 NA

问题描述

我努力根据第一个和最后一个非缺失值的不同条件以不同方式填写 NA。
背景:人们接受白内障手术并改变晶状体phak状态pseudo。如果第一个非缺失值是“phak”,则这必须存在于以前未记录的观察中。如果最后一个非缺失值是“伪”,则可以继续进行,因为状态不能变回“phak”。
不能简单地使用这样的函数,zoo::na.locf因为如果在 switch 之间存在 NA,我们将无法确定操作的确切时间,并且这些值应该保持 NA。因此,这不是一个“三明治”问题

library(tidyverse)

a <- c(NA, 'phak', NA, 'pseudo', NA)
b <- c(NA, 'pseudo', NA, NA, NA)
c <- c('phak', 'phak', NA, NA, NA)

dfoo <- data.frame(a,b,c, stringsAsFactors = FALSE) %>% gather(eye, status)
dfoo
#>      eye status
#> 1      a   <NA>
#> 2      a   phak
#> 3      a   <NA>
#> 4      a pseudo
#> 5      a   <NA>
#> 6      b   <NA>
#> 7      b pseudo
#> 8      b   <NA>
#> 9      b   <NA>
#> 10     b   <NA>
#> 11     c   phak
#> 12     c   phak
#> 13     c   <NA>
#> 14     c   <NA>
#> 15     c   <NA>

所需的数据框:

#>      eye  status
#> 1      a   phak
#> 2      a   phak
#> 3      a   <NA>
#> 4      a pseudo
#> 5      a pseudo
#> 6      b   <NA>
#> 7      b pseudo
#> 8      b pseudo
#> 9      b pseudo
#> 10     b pseudo
#> 11     c   phak
#> 12     c   phak
#> 13     c   <NA>
#> 14     c   <NA>
#> 15     c   <NA>

以下适用于简单的 vector,但我很难在数据帧中按组使用此解决方案。

# by vector:
# first conditionally replace leading NAs
if(a[min(which(!is.na(a)))] == 'phak') {a[1 : min(which(!is.na(a)))] <- 'phak'}
# next conditionally replace last NAs
if(a[max(which(!is.na(a)))] == 'pseudo') {a[max(which(!is.na(a))): length(a)] <- 'pseudo'}

a
#> [1] "phak"   "phak"   NA       "pseudo" "pseudo"

reprex 包(v0.3.0)于 2019 年 12 月 16 日创建

标签: r

解决方案


这是一种可能的 tidyverse 方法:

  1. group_by视线水平
  2. 创建两个临时列phakpseudo分别替换所有"pseudo"值和"phak"NA
  3. fill使用的phak.direction = "up"
  4. fill使用的pseudo.direction = "down"
  5. coalescephak和列在pseudo列中重新组合在一起status
library(tidyverse)

dfoo %>%
    group_by(eye) %>%
    mutate(
        phak = na_if(status, "pseudo"),
        pseudo = na_if(status, "phak")
    ) %>%
    fill(phak, .direction = "up") %>%
    fill(pseudo, .direction = "down") %>%
    transmute(status = coalesce(phak, pseudo)) %>%
    ungroup()
#> # A tibble: 15 x 2
#>    eye   status
#>    <chr> <chr> 
#>  1 a     phak  
#>  2 a     phak  
#>  3 a     <NA>  
#>  4 a     pseudo
#>  5 a     pseudo
#>  6 b     <NA>  
#>  7 b     pseudo
#>  8 b     pseudo
#>  9 b     pseudo
#> 10 b     pseudo
#> 11 c     phak  
#> 12 c     phak  
#> 13 c     <NA>  
#> 14 c     <NA>  
#> 15 c     <NA>

数据

dfoo <- structure(list(eye = c("a", "a", "a", "a", "a", "b", "b", "b", 
            "b", "b", "c", "c", "c", "c", "c"), status = c(NA, "phak", NA, 
            "pseudo", NA, NA, "pseudo", NA, NA, NA, "phak", "phak", NA, NA, 
            NA)), row.names = c(NA, -15L), class = "data.frame")

推荐阅读