apply()为每列提供NA值

问题描述:

最近我一直有这个奇怪的问题apply。请看下面的例子:apply()为每列提供NA值

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值,我没有任何问题:我的含data.framenumericcharacter数据当试图

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

但是,它忽视了:

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 

?apply描述的第一句:

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

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

我想我欠你一个替代的描述,所以在这里你去。数据帧实际上只是列表,所以如果要将函数应用于每列,请改为使用lapplysapply

apply工作在一个矩阵上,并且矩阵必须全部是一种类型。所以df正在被转换成一个矩阵,并且由于它包含一个字符,所有的列都变成了字符。

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

为了得到你想要的东西,检查出plyrcolwisenumcolwise功能。

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

您正在将一个函数应用于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 
+0

你也可以使用'suppressWarnings(sapply(df,mean))'去除警告。然而,这会抑制任何警告,而您的版本只会抑制我们知道会发生的警告,并且不关心,因此您的警告可能是更好的解决方案。 – Dason 2012-04-02 22:10:01