如何在R中处理空数据框?

4
我注意到在我的R脚本中有时会出现错误,当我忘记检查我正在处理的数据框是否为空(没有任何行)时会发生这种情况。例如,当我像这样使用apply时:
apply(X=DF,MARGIN=1,FUN=function(row) !any(vec[ row[["start"]]:row[["end"]] ]))
如果DF恰好是空的,我会收到关于下标的错误。为什么会这样?空数据框不是有效的吗?当数据框中没有行时,为什么带有MARGIN=1的apply()会尝试执行任何操作?我真的需要在每个这样的apply之前添加一个条件来确保数据框不为空吗?
谢谢!

你是不是把标准的*pplys和plyr混淆了? - mbq
在出现空的 data.frame 时,您希望什么样的结果?列表? NULLNAFALSE?也许您可以在代码中早些时候消除空的 data.frame - Marek
@mbq 我不确定。当我使用apply()MARGIN=1时,它是如何工作的?我认为它会将每一行发送到FUN并聚合结果。 - David B
抱歉,这个评论很愚蠢,请忽略。 - mbq
4个回答

3

这与apply完全无关。当数据框为空时,您应用的函数无法正常工作。

> myFUN <- function(row) !any(vec[ row[["start"]]:row[["end"]] ])
> myFUN(DF[1,])  # non-empty data.frame
[1] FALSE
> myFUN(data.frame()[1,])  # empty data.frame
Error in row[["start"]]:row[["end"]] : argument of length 0

在您的函数中添加一个条件。
> apply(X=data.frame(),MARGIN=1,  # empty data.frame
+  FUN=function(row) {
+    if(length(row)==0) return()
+    !any(vec[ row[["start"]]:row[["end"]] ])
+  })
NULL

我不确定我理解apply(MARGIN=1)的工作原理。我认为它会将每一行发送到FUN并聚合结果。如果是这样的话,一个空数据框不应该失败,因为FUN永远不会被调用。所以我猜这不是这种情况。我查看了文档,但仍然没有完全弄清楚它的工作原理。 - David B
apply 不会进行聚合。它将对 X 的部分(“边缘”)调用 FUN 的结果放入一个对象中。该对象在 ?apply 的“Value”部分的第一段中定义。我不确定为什么您认为如果 X 为空,FUN 就不会被调用;文档甚至没有暗示这种行为。 - Joshua Ulrich
我知道这是一个旧答案,但是当数据框不为空但包含值时会发生什么?我相信如果你将一个有多行的数据框放入这个函数中,它会抛出一个错误。 - Kevin

3

顺便说一下:apply函数总是至少访问你使用的函数一次。如果输入是一个没有任何行但有定义变量的数据框,则将“FALSE”作为参数发送给函数。如果数据框完全为空,则向函数发送logical(0)。

> x <- data.frame(a=numeric(0))
> str(x)
'data.frame':   0 obs. of  1 variable:
 $ a: num 

> y <- apply(x,MARGIN=1,FUN=function(x){print(x)})
[1] FALSE

> x <- data.frame()

> str(x)
'data.frame':   0 obs. of  0 variables

> y <- apply(x,MARGIN=1,FUN=function(x){print(x)})
logical(0)

因此,正如Joshua已经告诉您的那样,在应用之前控制数据框是否有行,或在应用中添加一个条件函数。
编辑: 这意味着您应该考虑到length(x)==0不是一个很好的检查,如果两种可能性都可能出现,您需要检查x==0的长度或!x是否为TRUE: (代码来自Joshua)
apply(X=data.frame(),MARGIN=1,  # empty data.frame
  FUN=function(row) {
    if(length(row)==0 || !row) {return()}
    !any(vec[ row[["start"]]:row[["end"]] ])
  })

1
我认为最好使用if(length(row)==0 || !row)(而不是|),否则我们可能会收到警告,提示“条件长度>1,只有第一个元素将被使用”。 - David B
请问 apply 的这种行为在哪里有文档记录? - David B
@David:在上面的代码中。有时候自己测试一下就能得到很多见解。我记得我之前试过它。 - Joris Meys
1
“Apply总是访问您至少使用一次的函数” - 感谢指出这一点。这个行为真的让我感到困惑,尽管我已经阅读了该函数的文档。如果没有这个答案,我怎么会知道它会这样做呢?谢谢! - Yetanotherjosh
@Yetanotherjosh 我在帮助文件中没有找到这个确切的语句,但是通过理解函数的工作原理并进行测试,我得出了这个结论。通过尝试,我学到了很多关于R语言的知识。 - Joris Meys

1

我认为这与0行数据框无关:

X <- data.frame(a=numeric(0))
str(X)
# 'data.frame':   0 obs. of  1 variable:
# $ a: num 
apply(X,1,sum)
# integer(0)

尝试在错误发生后使用traceback()来查看具体是什么导致了错误。

1
我会使用mapply代替:
kk <- data.frame( start = integer(0), end = integer(0) )
kkk <- data.frame( start = 1, end = 3 )

vect <- rnorm( 100 ) > 0

with(kk,  mapply( function(x, y) !any( vect[x]:vect[y] ), start, end ) )
with(kkk, mapply( function(x, y) !any( vect[x]:vect[y] ), start, end ) )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接