apply()为每列提供NA值

时间:2012-03-14 21:22:44

标签: r apply

我最近遇到了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

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

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

但是,在尝试使用包含data.framenumeric数据的character时,它似乎失败了:

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

当然,我希望获得NA列的character,但我希望获得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

3 个答案:

答案 0 :(得分:10)

?apply说明的第一句话说:

  

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

矩阵只能是R中的单一类型。当数据框被强制转换为矩阵时,如果只有一个字符列,则所有内容都以字符结尾。

我想我欠你一个替代品的描述,所以你走了。数据框实际上只是列表,因此如果要将函数应用于每列,请改用lapplysapply

答案 1 :(得分:3)

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

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

要获得所需内容,请查看colwise中的numcolwiseplyr功能。

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

答案 2 :(得分:2)

您正在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

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

sapply(df, function(x)ifelse(is.numeric(x), mean(x), NA))

speed  dist   foo 
15.40 42.98    NA