【问题标题】:R apply function across rows, unexpected answerR跨行应用函数,意外答案
【发布时间】:2014-07-11 19:43:03
【问题描述】:

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

设置:

> 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 和6)。为了验证非apply'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) 我想要它在行方向上(我将“1”传递给第二个参数),并且 (b) 值“x”是只放行id,不放列id?

我知道还有其他可能更好的方法来做我想做的事情(在新列中找到已更改为 NA 的行。但请不要在答案中提供。相反,请解释为什么apply 没有按我的预期工作,以及我可以做些什么来解决它。

【问题讨论】:

  • 您不应该将df 传递给匿名function(x),它已经为您逐行细分了apply(df, 1, function(x) (any(is.na(x[3:4]))))
  • 嗨 Rawr,这正是我想要的!如果您将其放入答案中,我会竖起大拇指并勾选正确。

标签: r apply


【解决方案1】:

要查找具有 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

【讨论】:

  • 我试图在这里表达期望。我想要按行而不是按列的信息。抱歉,如果这不够清楚。据我所知,apply 是唯一可以让我按行工作的矢量化。
  • @MikeWilliamson 哈哈,不,当您在 OP 中明确说“按列”时,它并不是“足够清楚”,但是好的,只需将 sapply 替换为 apply(df, 1, ...
【解决方案2】:

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

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

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

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

> 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

您说您想知道哪些 引入了NAs,但您却applying 超过行。如果您真的想使用apply(我推荐@eddi 的方法),您可以这样做:

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

【讨论】:

    【解决方案3】:

    你可以使用

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

    查找包含NAs 的行。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-01
      • 1970-01-01
      相关资源
      最近更新 更多