dplyr: заменить NA и 0 на условные подгруппы - PullRequest
0 голосов
/ 10 июня 2018

Я пытаюсь заменить все NA и 0 в большом наборе данных на их среднее значение по группе - вычисленное на основе случаев, которые не являются NA или 0.

Source: local data frame [174,019 x 3]
Groups: name

   student   name  hours
1       s1    ABC    1.0
2       s1    DEF     NA
3       s2    DEF    0.5
4       s3     NA    2.0
5       s3    ABC    2.0
6       s4    GHI      0

Это решение с использованием dplyr работает как задумано, но можно ли это сделать в одной цепочке?

avg <- workshops %>%
  filter(hours > 0 & !is.na(name)) %>%
  group_by(name) %>%
  summarize(avg.hours = mean(hours, na.rm = TRUE))

workshops <- workshops %>%
  left_join(avg, by = "name") %>%
  mutate(hours = if_else(hours > 0, hours, avg.hours, avg.hours)) %>%
  select(-avg.hours)

Обновленное решение

workshop <- workshop %>%
  group_by(name) %>%
  mutate(hours = ifelse(!is.na(name), replace(hours, hours == 0 | is.na(hours),
                 mean(`is.na<-`(hours, hours == 0), na.rm = TRUE)), NA))

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Вот вариант с na.aggregate из zoo.После группировки по имени измените 0 на NA с помощью na_if и примените na.aggregate, чтобы заменить отсутствующие значения на mean (по умолчанию параметр FUN равен mean)

library(dplyr)
library(zoo)
workshops %>%
    group_by(name) %>% 
    mutate(hours = na.aggregate(na_if(hours, 0))) 

данные

workshops <- structure(list(student = c("s1", "s1", "s2", "s3", "s3", 
 "s4"), name = c("ABC", "DEF", "DEF", NA, "ABC", "GHI"),
 hours = c(1, NA, 0.5, 2, 2, 0)), .Names = c("student", "name", "hours"), 
 class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6"))
0 голосов
/ 10 июня 2018

Вы можете сделать:

workshop%>%
  group_by(name)%>%
  mutate(hours=replace(hours,hours==0|is.na(hours),
                 mean(`is.na<-`(hours,hours==0),na.rm = T)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...