Разбиение таблицы данных с помощью оператора: функции, возвращающие числовые значения и/или неудача NA
У меня есть data.table
с двумя столбцами: один столбец ID
и один столбец value
. Я хочу разбить таблицу на столбец ID
и запустить функцию foo
в столбце value
. Это работает отлично, пока foo
не возвращает NA. В этом случае я получаю сообщение об ошибке, которое говорит мне, что типы групп несовместимы. Мое предположение заключается в том, что поскольку is.logical(NA)
равно TRUE
и is.numeric(NA)
равно FALSE
, data.table
внутренне предполагает, что я хочу комбинировать логические значения с числовыми и возвращает ошибку. Однако я нахожу это поведение своеобразным. Любые комментарии по этому поводу? Я пропустил что-то очевидное здесь или это действительно предназначенное поведение? Если да, то короткое объяснение было бы замечательным. (Обратите внимание, что я знаю обход: просто пусть foo2
вернет полное невероятное число и фильтр для этого позже. Однако это выглядит плохое кодирование).
Вот пример:
library(data.table)
foo1 <- function(x) {if (mean(x) < 5) {return(1)} else {return(2)}}
foo2 <- function(x) {if (mean(x) < 5) {return(1)} else {return(NA)}}
DT <- data.table(ID=rep(c("A", "B"), each=5), value=1:10)
DT[, foo1(value), by=ID] #Works perfectly
ID V1
[1,] A 1
[2,] B 2
DT[, foo2(value), by=ID] #Throws error
Error in `[.data.table`(DT, , foo2(value), by = ID) :
columns of j don't evaluate to consistent types for each group: result for group 2 has column 1 type 'logical' but expecting type 'numeric'
Ответы
Ответ 1
Вы можете исправить это, указав, что ваша функция должна возвращать NA_real_
, а не NA
по умолчанию.
foo2 <- function(x) {if (mean(x) < 5) {return(1)} else {return(NA)}}
DT[, foo2(value), by=ID] #Throws error
# Error in `[.data.table`(DT, , foo2(value), by = ID) :
# columns of j don't evaluate to consistent types for each group:
# result for group 2 has column 1 type 'logical' but expecting type 'numeric'
foo3 <- function(x) {if (mean(x) < 5) {return(1)} else {return(NA_real_)}}
DT[, foo3(value), by=ID] #Works
# ID V1
# [1,] A 1
# [2,] B NA
Кстати, сообщение, которое foo2()
дает, когда оно терпит неудачу, очень информативно. По сути, это говорит о том, что ваш NA неправильного типа. Чтобы устранить проблему, вам просто нужно искать константу NA
для правильного типа (или класса):
NAs <- list(NA, NA_integer_, NA_real_, NA_character_, NA_complex_)
data.frame(contantName = sapply(NAs, deparse),
class = sapply(NAs, class),
type = sapply(NAs, typeof))
# contantName class type
# 1 NA logical logical
# 2 NA_integer_ integer integer
# 3 NA_real_ numeric double
# 4 NA_character_ character character
# 5 NA_complex_ complex complex