Обходной путь - просто не использовать NA
для групп значений.Во-первых, инициализируйте ваши данные, как указано выше:
x <- data.frame(idx=1:30, group=rep(letters[1:10],3), val=runif(30))
x$val[sample.int(nrow(x), 5)] <- NA; x
spl <- with(x, split(x, group))
lpp <- lapply(spl,
function(x) { r <- with(x,
data.frame(x, val_g=cut(val, seq(0,1,0.1), labels = FALSE),
val_g_lab=cut(val, seq(0,1,0.1)))); r })
rd <- do.call(rbind, lpp);
ord <- rd[order(rd$idx, decreasing = FALSE), ];
Просто преобразуйте в символьные и скрытые NA в произвольный строковый литерал:
# Convert to character
ord$val_g_lab <- as.character(ord$val_g_lab)
# Convert NAs
ord$val_g_lab[is.na(ord$val_g_lab)] <- "Unknown"
aggregate(val ~ group + val_g_lab, ord,
FUN=function(x) c(mean(x, na.rm = FALSE), sum(!is.na(x))),
na.action=na.pass)
# group val_g_lab val.1 val.2
#1 e (0,0.1] 0.02292533 1.00000000
#2 g (0.1,0.2] 0.16078353 1.00000000
#3 g (0.2,0.3] 0.20550228 1.00000000
#4 i (0.2,0.3] 0.26986665 1.00000000
#5 j (0.2,0.3] 0.23176149 1.00000000
#6 d (0.3,0.4] 0.39196441 1.00000000
#7 e (0.3,0.4] 0.39303518 1.00000000
#8 g (0.3,0.4] 0.35646994 1.00000000
#9 i (0.3,0.4] 0.35724889 1.00000000
#10 a (0.4,0.5] 0.48809261 1.00000000
#11 b (0.4,0.5] 0.40993166 1.00000000
#12 d (0.4,0.5] 0.42394859 1.00000000
# ...
#20 b (0.9,1] 0.99562918 1.00000000
#21 c (0.9,1] 0.92018049 1.00000000
#22 f (0.9,1] 0.91379088 1.00000000
#23 h (0.9,1] 0.93445802 1.00000000
#24 j (0.9,1] 0.93325098 1.00000000
#25 b Unknown NA 0.00000000
#26 c Unknown NA 0.00000000
#27 d Unknown NA 0.00000000
#28 i Unknown NA 0.00000000
#29 j Unknown NA 0.00000000
Делает ли это то, что вы хотите?
Редактировать:
Чтобы ответить на ваш вопрос в комментариях.Примечание NaN
и NA
не совсем одинаковы (см. здесь ).Также обратите внимание, что эти два элемента очень отличаются от "NaN"
и "NA"
, которые являются строковыми литералами (то есть просто текстом)Но в любом случае NA
s - это специальные «атомарные» элементы, которые почти всегда обрабатываются исключительно функциями.Таким образом, вы должны посмотреть в документации, как конкретная функция обрабатывает NA
s.В этом случае аргумент na.action
применяется к значениям, по которым вы агрегируете, а не к «классам» в вашей формуле.Аргумент drop=FALSE
также можно использовать, но тогда вы получите все комбинации (в данном случае) двух классификаций.Переопределение NA
к строковому литералу работает, потому что новое имя обрабатывается как любой другой класс.