R跨行应用函数,意外答案

时间:2014-07-11 19:43:03

标签: r apply

我不明白这里发生了什么:

设置:

> df = data.frame(x1= rnorm(10), x2= rnorm(10))
> df[3,1] <- "the"
> df[6,2] <- "NA"
## I want to create values that will be challenging to coerce to numeric
> df$x1.fixed <- as.numeric(df$x1)
> df$x2.fixed <- as.numeric(df$x2)
## Here is the DF
> df
                   x1                 x2   x1.fixed   x2.fixed
1   0.955965351551298 -0.320454533088042  0.9559654 -0.3204545
2   -1.87960909714257   1.61618672247496 -1.8796091  1.6161867
3                 the -0.855930398468875         NA -0.8559304
4  -0.400879592905882 -0.698655375066432 -0.4008796 -0.6986554
5   0.901252404134257  -1.08020133150191  0.9012524 -1.0802013
6    0.97786920899034                 NA  0.9778692         NA
.
.
.
> table(is.na(df[,c(3,4)]))

FALSE  TRUE 
   18     2 

我想找到 转换为NAs 的行,因此我提出了一个复杂的应用程序,但没有按预期工作。然后我简化并再次尝试......

问题:

更简单的电话:

> apply(df, 1, function(x) (any(is.na(df[x,3]), is.na(df[x,4]))))

意外地产生了:

[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

相反,我预计:

[1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE

突出显示存在NA的行(3&amp; 6)。要验证非apply&#39; ed函数是否有效,我尝试了:

> any(is.na(df[3,1]), is.na(df[3,2]))
[1] FALSE
> any(is.na(df[3,3]), is.na(df[3,4]))
[1] TRUE

正如所料。为了进一步混淆apply正在做什么,我尝试了:

> apply(df, 1, function(x) is.na(df[x,1]))
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE  TRUE
[2,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE  TRUE
[3,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE  TRUE
[4,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE  TRUE

为什么这会遍历整个DF,当我清楚地指出(a)我想要它在行方向(我通过&#34; 1&#34;到第二个参数),和(b)价值&#34; x&#34;只放在行id中,而不是列id?

我知道还有其他的,也许更好的方法可以做我想做的事情(在新列中找到已更改为NA的行。但请不要提供在答案中。请解释为什么apply没有像我期望的那样起作用,以及我可以做些什么来解决它。

3 个答案:

答案 0 :(得分:2)

要查找具有NA的列,您可以执行以下操作:

sapply(df, function(x) any(is.na(x)))
#      x1       x2 x1.fixed x2.fixed 
#   FALSE    FALSE     TRUE     TRUE 

data.frame是一个向量列表,因此sapply中的上述函数将为该列表的每个元素(即每列)评估any(is.na(

根据OP编辑 - 要获取具有NA的行,请改为使用apply(df, 1, ...

apply(df, 1, function(x) any(is.na(x)))
# [1] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE

答案 1 :(得分:1)

apply正在按照预期完全工作。你的期望是错误的。

apply(df, 1, function(x) is.na(df[x,1]))

apply执行的第一件事(根据文档)将数据框强制转换为矩阵。在此过程中,所有数字列都被强制转换为字符。

接下来,将df的每个作为参数x传递给您的函数。在df 的第一行中字符值索引df在什么意义上是有意义的?所以你得到了一堆NA。您可以通过以下方式测试:

> df[as.character(df[1,]),]
       x1   x2 x1.fixed x2.fixed
NA   <NA> <NA>       NA       NA
NA.1 <NA> <NA>       NA       NA
NA.2 <NA> <NA>       NA       NA
NA.3 <NA> <NA>       NA       NA

你说你想知道哪些引入了NA,但你却apply在行上。如果真的想要使用apply(我推荐@ eddi的方法),你可以这样做:

apply(df,2,function(x) any(is.na(x)))

答案 2 :(得分:0)

您可以使用

rowSums(is.na(df))>0
[1] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE

查找包含NA s。

的行

我不确定,但我认为这是一个矢量化操作,如果您处理大数据,可能比使用apply更快。