Используйте агрегат и сохраняйте ряды NA - PullRequest
0 голосов
/ 09 октября 2018

Я не тратил такое время на одно единственное задание, подобное этому, годами.

Здесь, на SO, есть несколько подсказок, например: здесь или здесь , поэтому возникает соблазн сказать, что это дубликат (я бы даже сказал).Но с примерами и множественными испытаниями я не смог выполнить то, что нужно.

Вот полный пример:

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), ]; ord

aggregate(val ~ group + val_g_lab, ord, 
          FUN=function(x) c(mean(x, na.rm = FALSE), 
                            sum(!is.na(x))), na.action=na.pass)

Желаемый результат: я хотел бы, чтобы также были включены NA,после aggregate().В настоящее время aggregate() отбрасывает строки АН.

      idx group        val val_g val_g_lab  
 a.1    1     a 0.53789249     6 (0.5,0.6]          
 b.2    2     b 0.01729695     1   (0,0.1]          
 c.3    3     c 0.62295270     7 (0.6,0.7]          
 d.4    4     d 0.60291892     7 (0.6,0.7]
 e.5    5     e 0.76422909     8 (0.7,0.8]
 f.6    6     f 0.87433547     9 (0.8,0.9]
 g.7    7     g         NA    NA      <NA>          
 h.8    8     h 0.50590159     6 (0.5,0.6]
 i.9    9     i 0.89084068     9 (0.8,0.9]
 ...... continue (full data set as @ord object.

1 Ответ

0 голосов
/ 09 октября 2018

Обходной путь - просто не использовать 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 к строковому литералу работает, потому что новое имя обрабатывается как любой другой класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...