2012-03-14 3 views
4

У меня была эта странная проблема с 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 применить функцию fun (скажем, mean) на каждой колонке этой data.frame. Если data.frame является содержащий только numeric значения, у меня нет никаких проблем:

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

Но при попытке с моей data.frame, содержащих numeric и 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 

ответ

10

В первом предложении описания для ?apply говорит:

Если X не является массивом, а объект класса с ненулевым значением тусклый (например, кадр данных) , применяйте попытки принудительного принуждения к массиву через as.matrix, если он двумерный (например, кадр данных) или через as.array.

Матрицы могут быть только одного типа в R. Когда кадр данных принуждается к матрице, все заканчивается как символ, если есть даже столбец с одним символом.

Я предполагаю, что я должен вам описание альтернативы, поэтому здесь вы идете. кадры данных действительно являются списками, поэтому, если вы хотите применить функцию к каждому столбцу, вместо этого используйте lapply или sapply.

3

apply работает на матрице, а матрица должна быть одного типа. Таким образом, df преобразуется в матрицу, и поскольку он содержит символ, все столбцы становятся символом.

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

Чтобы получить то, что вы хотите, проверить colwise и numcolwise функции в plyr.

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

Вы применяете функцию по столбцам data.frame. Поскольку данные.кадр является список, вы можете использовать lapply или sapply вместо 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

Смежные вопросы