Make elements NA depending on a predicate function

不羁岁月 提交于 2019-12-12 15:14:36

问题


How can I easily change elements of a list or vectors to NAs depending on a predicate ?

I need it to be done in a single call for smooth integration in dplyr::mutate calls etc...

expected output:

make_na(1:10,`>`,5)
# [1]  1  2  3  4  5 NA NA NA NA NA

my_list <- list(1,"a",NULL,character(0))    
make_na(my_list, is.null)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] "a"
# 
# [[3]]
# [1] NA
# 
# [[4]]
# character(0)

Note:

I answered my question as I have one solution figured out but Id be happy to get alternate solutions. Also maybe this functionality is already there in base R or packaged in a prominent library

Was inspired by my frustration in my answer to this post


回答1:


We can build the following function:

make_na <- function(.x,.predicate,...) {
  is.na(.x) <- sapply(.x,.predicate,...)
  .x
}

Or a bit better to leverage purrr's magic :

make_na <- function(.x,.predicate,...) {
  if (requireNamespace("purrr", quietly = TRUE)) {
    is.na(.x) <- purrr::map_lgl(.x,.predicate,...)
  } else {
    if("formula" %in% class(.predicate))
      stop("Formulas aren't supported unless package 'purrr' is installed") 
    is.na(.x) <- sapply(.x,.predicate,...)
  }
  .x
}

This way we'll be using purrr::map_lgl if library purrr is available, sapply otherwise.

Some examples :

make_na <- function(.x,.predicate,...) {
  is.na(.x) <- purrr::map_lgl(.x,.predicate,...)
  .x
}

Some use cases:

make_na(1:10,`>`,5)
# [1]  1  2  3  4  5 NA NA NA NA NA

my_list <- list(1,"a",NULL,character(0))
make_na(my_list, is.null)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] "a"
# 
# [[3]]
# [1] NA
# 
# [[4]]
# character(0)

make_na(my_list, function(x) length(x)==0)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] "a"
# 
# [[3]]
# [1] NA
# 
# [[4]]
# [1] NA

If purrr is installed we can use this short form:

make_na(my_list, ~length(.x)==0)


来源:https://stackoverflow.com/questions/50665776/make-elements-na-depending-on-a-predicate-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!