Подтвердить что ты не робот

Функция `as.na`

В R почти каждая функция is.*, о которой я могу думать, имеет соответствующий as.*. Существует is.na, но не as.na. Почему бы и нет, если бы такая функция имела смысл?

У меня есть вектор x, который может быть logical, character, integer, numeric или complex, и я хочу преобразовать его в вектор того же класса и длины, но заполненный соответствующий: NA, NA_character_, NA_integer_, NA_real_ или NA_complex_.

Моя текущая версия:

as.na <- function(x) {x[] <- NA; x}
4b9b3361

Ответ 1

Почему бы не использовать is.na<- как указано в ?is.na?

> l <- list(integer(10), numeric(10), character(10), logical(10), complex(10))
> str(lapply(l, function(x) {is.na(x) <- seq_along(x); x}))
List of 5
 $ : int [1:10] NA NA NA NA NA NA NA NA NA NA
 $ : num [1:10] NA NA NA NA NA NA NA NA NA NA
 $ : chr [1:10] NA NA NA NA ...
 $ : logi [1:10] NA NA NA NA NA NA ...
 $ : cplx [1:10] NA NA NA ...

Ответ 2

Кажется, это будет последовательно быстрее, чем ваша функция:

as.na <- function(x) {
    rep(c(x[0], NA), length(x))
}

(Благодаря Джошуа Ульриху, указав, что моя предыдущая версия не сохранила атрибуты класса.)


Здесь для записи есть некоторые относительные тайминги:

library(rbenchmark)

## The functions
flodel <- function(x) {x[] <- NA; x}
joshU <- function(x) {is.na(x) <- seq_along(x); x}
joshO <- function(x) rep(c(x[0], NA), length(x))

## Some vectors to  test them on
int  <- 1:1e6
char <- rep(letters[1:10], 1e5)
bool <- rep(c(TRUE, FALSE), 5e5)

benchmark(replications=100, order="relative",
    flodel_bool = flodel(bool),
    flodel_int  = flodel(int),
    flodel_char = flodel(char),
    joshU_bool = joshU(bool),
    joshU_int  = joshU(int),
    joshU_char = joshU(char),
    joshO_bool = joshO(bool),
    joshO_int  = joshO(int),
    joshO_char = joshO(char))[1:6]        
#          test replications elapsed relative user.self sys.self
# 7  joshO_bool          100    0.46    1.000      0.33     0.14
# 8   joshO_int          100    0.49    1.065      0.31     0.18
# 9  joshO_char          100    1.13    2.457      0.97     0.16
# 1 flodel_bool          100    2.31    5.022      2.01     0.30
# 2  flodel_int          100    2.31    5.022      2.00     0.31
# 3 flodel_char          100    2.64    5.739      2.36     0.28
# 4  joshU_bool          100    3.78    8.217      3.13     0.66
# 5   joshU_int          100    3.95    8.587      3.30     0.64
# 6  joshU_char          100    4.22    9.174      3.70     0.51

Ответ 3

Функция не существует, потому что это не преобразование типа. Преобразование типа будет меняться от 1L до 1.0 или с изменением "1" на 1L. Тип NA не является преобразованием из другого типа, если только этот тип не был текстовым. Учитывая, что существует только один тип, из которого возможно преобразовать, и существует так много вариантов выполнения назначения NA (как и во многих других ответах), нет никакой необходимости в такой функции.

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

Ответ 4

Старый вопрос, но как насчет

as.na <- function(obj){
  if(is.factor(obj)){
    # Special case for factors - any others that need to be handled?
    factor(rep(NA, length(obj)), levels = levels(obj))
  } else{
    objClass <- class(obj)
    x <- rep(NA, length(obj))
    class(x) <- objClass 
    x
  }
}

Для фреймов данных:

DF <- data.frame(
  int = seq(1, 10),
  real = seq(1, 10) + 0.1,
  char = letters[1:10],
  logi = rep(c(TRUE, FALSE), 5),
  Date = seq.Date(as.Date("2019-09-03"), by = 1, length.out = 10),
  posix = seq.POSIXt(as.POSIXct("2019-09-03 12:00:00"), by = 360, length.out = 10),
  stringsAsFactors = FALSE
) 
DF$factr <- as.factor(LETTERS[1:10])
str(DF)
'data.frame':   10 obs. of  7 variables:
 $ int  : int  1 2 3 4 5 6 7 8 9 10
 $ real : num  1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 10.1
 $ char : chr  "a" "b" "c" "d" ...
 $ logi : logi  TRUE FALSE TRUE FALSE TRUE FALSE ...
 $ Date : Date, format: "2019-09-03" "2019-09-04" "2019-09-05" ...
 $ posix: POSIXct, format: "2019-09-03 12:00:00" "2019-09-03 12:06:00" "2019-09-03 12:12:00" ...
 $ factr: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 6 7 8 9 10

DF_na <- DF
for(i in colnames(DF_na)){
  DF_na[,i] <- as.na(DF_na[,i])
}

str(DF_na)
'data.frame':   10 obs. of  7 variables:
 $ int  : int  NA NA NA NA NA NA NA NA NA NA
 $ real : num  NA NA NA NA NA NA NA NA NA NA
 $ char : chr  NA NA NA NA ...
 $ logi : logi  NA NA NA NA NA NA ...
 $ Date : Date, format: NA NA NA ...
 $ posix: POSIXct, format: NA NA NA ...
 $ factr: Factor w/ 10 levels "A","B","C","D",..: NA NA NA NA NA NA NA NA NA NA

Для data.tables:

library(data.table)

DT <- data.table::data.table(
  int = seq(1, 10),
  real = seq(1, 10) + 0.1,
  char = letters[1:10],
  logi = rep(c(TRUE, FALSE), 5),
  Date = seq.Date(as.Date("2019-09-03"), by = 1, length.out = 10),
  posix = seq.POSIXt(as.POSIXct("2019-09-03 12:00:00"), by = 360, length.out = 10),
  factr = as.factor(LETTERS[1:10])
)
str(DT)
Classes ‘data.table and 'data.frame':  10 obs. of  7 variables:
 $ int  : int  1 2 3 4 5 6 7 8 9 10
 $ real : num  1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 10.1
 $ char : chr  "a" "b" "c" "d" ...
 $ logi : logi  TRUE FALSE TRUE FALSE TRUE FALSE ...
 $ Date : Date, format: "2019-09-03" "2019-09-04" "2019-09-05" ...
 $ posix: POSIXct, format: "2019-09-03 12:00:00" "2019-09-03 12:06:00" "2019-09-03 12:12:00" ...
 $ factr: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 6 7 8 9 10
 - attr(*, ".internal.selfref")=<externalptr> 

DT_na <-
  copy(DT)[, lapply(.SD, as.na)]
str(DT_na)
Classes ‘data.table and 'data.frame':  10 obs. of  7 variables:
 $ int  : int  NA NA NA NA NA NA NA NA NA NA
 $ real : num  NA NA NA NA NA NA NA NA NA NA
 $ char : chr  NA NA NA NA ...
 $ logi : logi  NA NA NA NA NA NA ...
 $ Date : Date, format: NA NA NA ...
 $ posix: POSIXct, format: NA NA NA ...
 $ factr: Factor w/ 10 levels "A","B","C","D",..: NA NA NA NA NA NA NA NA NA NA
 - attr(*, ".internal.selfref")=<externalptr>