【问题标题】:How to check a data.frame for any non-finite如何检查 data.frame 是否有任何非有限
【发布时间】:2011-12-31 15:59:47
【问题描述】:

我想检查 data.frame 是否有任何非有限元素。

这似乎评估每一列,为每一列返回 FALSE(我猜它评估 data.frame 作为一个列表):

any( !is.finite( x ) )

我不明白为什么这与上面的行为不同,但如果只是检查 NA,它就可以正常工作:

any( !is.na( x ) )

我希望解决方案尽可能高效。我意识到我可以做到……

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

【问题讨论】:

  • 效率不错,但是...您有任何证据表明该测试的速度是(或将成为)您分析的瓶颈吗?
  • 它不太可能成为瓶颈。我认为这个问题是一个了解更多关于 R 的机会。我想知道我是否缺少一些技术来评估 data.frame 中的元素,而不是转换为不同数据类型的明显技术

标签: r


【解决方案1】:

您调用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's 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

【讨论】:

  • 关于 as.matrix、因子列和 vapply 的要点!这个答案充满了好东西。 =)
【解决方案2】:

如果您输入methods(is.na),您会看到它有一个data.frame 方法,这可能解释了为什么它按您期望的方式工作,而is.finite 没有。通常的解决方案是自己写一个,因为它只有一行。可能是这样的,

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

【讨论】:

  • 感谢指向 methods() 的指针以及解决方案!我会使用“all”而不是“any”,并将有限的 data.frame 列定义为只有有限的列
  • @SFun28 好点,谢谢。打字有点太快了。编辑以反映您的观点。
【解决方案3】:

一个区别是is.nais.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)

但没有测试最有效的方法。

【讨论】:

  • 谢谢,布赖恩!我很欣赏 is.na.data.frame 的细分
【解决方案4】:

我假设您遇到的错误如下:

> 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) )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 2020-09-20
    • 2010-10-26
    • 1970-01-01
    • 2015-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多