Как проверить data.frame для любых не конечных

Я хочу проверить, имеет ли файл data.frame какие-либо не конечные элементы.

Кажется, что оценивается каждый столбец, возвращая FALSE для каждого (я предполагаю, что он оценивает data.frame как список):

any( !is.finite( x ) )

Я не понимаю, почему это ведет себя иначе, чем указано выше, но отлично работает, если просто проверять NA:

any( !is.na( x ) )

Я хочу, чтобы решение было максимально эффективным. Я понимаю, что могу просто сделать...

any( !is.finite( as.matrix( x ) ) )

Ответы

Ответ 1

Если вы наберете methods(is.na), вы увидите, что у него есть метод data.frame, который, вероятно, объясняет, почему он работает так, как вы ожидаете, где is.finite нет. Обычным решением было бы написать один, поскольку это только одна строка. Что-то вроде этого возможно,

is.finite.data.frame <- function(obj){
    sapply(obj,FUN = function(x) all(is.finite(x)))
}

Ответ 2

Я предполагаю, что ошибка, которую вы получаете, следующая:

> any( is.infinite( z ) )
Error in is.infinite(z) : default method not implemented for type 'list'

Эта ошибка связана с тем, что функции is.infinite() и is.finite() не реализованы с помощью метода data.frames. Функция is.na() имеет метод data.frame.

Способ обойти это - apply() функция для каждой строки, столбца или элемента в data.frame. Здесь пример с использованием sapply() для применения функции is.infinite() к каждому элементу:

x <- c(1:10, NA)
y <- c(1:11)
z <- data.frame(x,y)
any( sapply(z, is.infinite) )
 ## or

any( ! sapply(z, is.finite) )

Ответ 3

Ваше решение вызова as.matrix будет работать, только если data.frame имеет только числовые столбцы. В противном случае матрица, как правило, станет матрицей символов, и результат будет ложным везде...

@joran имеет хороший подход, но у вас будут проблемы с столбцами факторов, если вы не добавите метод для факторов и т.д....

is.finite(letters[1:3])         # FALSE - OK
is.finite(factor(letters[1:3])) # TRUE - WRONG!!

is.finite.factor <- function(obj){
    logical(length(obj))
}

is.finite(factor(letters[1:3])) # FALSE - OK

Кроме того, если вы хотите, чтобы проверка была как можно быстрее, вы должны избегать sapply и вместо этого использовать vapply.

d <- data.frame(matrix(runif(1e6), nrow=10), letters[1:10])

# @joran method
is.finite.data.frame <- function(obj){
    sapply(obj,FUN = function(x) all(is.finite(x)))
}

system.time( x <- is.finite(d) ) # 0.42 secs

# Using vapply instead...
is.finite.data.frame <- function(obj) {
    vapply(obj,FUN = function(x) all(is.finite(x)), logical(1))
}

system.time( y <- is.finite(d) ) # 0.20 secs

identical(x,y) # TRUE

Ответ 4

Одно отличие состоит в том, что is.na и is.finite - разные типы функций. is.na является общим и будет отправляться на основе класса аргумента.

> methods("is.na")
[1] is.na.data.frame      is.na.numeric_version is.na.POSIXlt        
[4] is.na.raster*        

   Non-visible functions are asterisked

Обратите внимание, в частности, что существует функция is.na.data.frame. Глядя на эту функцию:

> is.na.data.frame
function (x) 
{
    y <- do.call("cbind", lapply(x, "is.na"))
    if (.row_names_info(x) > 0L) 
        rownames(y) <- row.names(x)
    y
}
<bytecode: 00000000054F40F0>
<environment: namespace:base>

частью, выполняющей работу, является вызов do.call("cbind", lapply(x, "is.na")), который объединяет столбцы (cbind), которые являются результатом lapply(x, "is.na"). Запустив это только с примером data.frame(mtcars):

> lapply(mtcars, "is.na")
$mpg
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$cyl
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$disp
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$hp
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$drat
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$wt
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$qsec
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$vs
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$am
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$gear
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$carb
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

мы видим, что это действительно просто вычисление по столбцам, скомпонованное обратно в data.frame.

Сравните это с is.finite, у которого нет определенной функции для data.frames:

> methods("is.finite")
no methods were found

Фактически, это примитивный метод, означающий, что детали находятся в коде C, а не в коде R.

> is.finite
function (x)  .Primitive("is.finite")

Если вы хотите выполнить вычисление по столбцам с помощью is.finite, вы можете обернуть его, как is.na.data.frame.

> do.call(cbind, lapply(mtcars, is.finite))
       mpg  cyl disp   hp drat   wt qsec   vs   am gear carb
 [1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [2,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [3,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [4,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [5,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [6,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [7,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [8,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [9,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[10,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[11,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[12,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[13,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[14,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[15,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[16,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[17,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[18,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[19,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[20,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[21,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[22,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[23,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[24,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[25,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[26,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[27,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[28,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[29,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[30,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[31,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[32,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Этот последний может также быть получен как

sapply(mtcars, is.finite)

Нет тестирования на то, что было бы наиболее эффективным.