【问题标题】:apply() is giving NA values for every columnapply() 为每一列提供 NA 值
【发布时间】:2012-03-14 21:22:43
【问题描述】:

我最近在apply 上遇到了这个奇怪的问题。考虑以下示例:

set.seed(42)
df <- data.frame(cars, foo = sample(LETTERS[1:5], size = nrow(cars), replace = TRUE))
head(df)
  speed dist foo
1     4    2   E
2     4   10   E
3     7    4   B
4     7   22   E
5     8   16   D
6     9   10   C

我想使用apply 在该data.frame 的每一列上应用函数fun(例如mean)。如果data.frame 只包含numeric 值,我没有任何问题:

apply(cars, 2, mean)
speed  dist 
15.40 42.98 

但是当我尝试使用包含numericcharacter 数据的data.frame 时,它似乎失败了:

apply(df, 2, mean)
speed  dist   foo 
   NA    NA    NA 
Warning messages:
1: In mean.default(newX[, i], ...) :
  argument is not numeric or logical: returning NA
2: In mean.default(newX[, i], ..) :
  argument is not numeric or logical: returning NA                 
3: In mean.default(newX[, i], ...) :                              
  argument is not numeric or logical: returning NA

当然,我希望为character 列获取NA,但我还是想为numeric 列获取值。

sapply(df, class)
    speed      dist       foo 
"numeric" "numeric"  "factor" 

任何指针都将不胜感激,因为我觉得我在这里遗漏了一些非常明显的东西!

> sessionInfo()
R version 2.14.1 (2011-12-22)
Platform: x86_64-unknown-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8    
 [5] LC_MONETARY=en_GB.UTF-8    LC_MESSAGES=en_GB.UTF-8   
 [7] LC_PAPER=C                 LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

【问题讨论】:

    标签: r apply


    【解决方案1】:

    ?apply 描述的第一句话说:

    如果 X 不是一个数组,而是一个具有非 null 暗淡的类的对象 值(例如数据框),应用尝试将其强制为数组 如果它是二维的(例如,数据帧),则通过 as.matrix 或通过 as.array.

    矩阵在 R 中只能是单一类型。当数据框被强制转换为矩阵时,即使只有一个字符列,所有内容都会最终成为一个字符。

    我想我欠你一个替代方案的描述,所以你去吧。数据框实际上只是列表,因此如果您想对每一列应用函数,请改用lapplysapply

    【讨论】:

      【解决方案2】:

      apply 作用于矩阵,矩阵必须是一种类型。所以df 被转换成一个矩阵,因为它包含一个字符,所以所有的列都变成了字符。

      > apply(df, 2, class)
            speed        dist         foo 
      "character" "character" "character" 
      

      要获得您想要的,请查看plyr 中的colwisenumcolwise 函数。

      > numcolwise(mean)(df)
        speed  dist
      1  15.4 42.98
      

      【讨论】:

        【解决方案3】:

        您正在对 data.frame 的列应用函数。由于data.frame是一个列表,你可以使用lapplysapply代替apply

        sapply(df, mean)
        
        speed  dist   foo 
        15.40 42.98    NA 
        Warning message:
        In mean.default(X[[3L]], ...) :
          argument is not numeric or logical: returning NA
        

        您可以通过使用匿名函数在计算平均值之前测试类 numeric 来删除警告消息:

        sapply(df, function(x)ifelse(is.numeric(x), mean(x), NA))
        
        speed  dist   foo 
        15.40 42.98    NA 
        

        【讨论】:

        • 您也可以使用suppressWarnings(sapply(df, mean)) 删除警告。但是,这将抑制任何警告,而您的版本只会抑制我们知道会发生且不关心的警告,因此您的版本可能是更好的解决方案。
        猜你喜欢
        • 2020-09-08
        • 1970-01-01
        • 2011-01-17
        • 2021-12-09
        • 2018-12-11
        • 1970-01-01
        • 2018-03-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多