Функция для замены отсутствующего на медиану для всего фрейма данных

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

library(dplyr)
test = data.frame(a=1:6,b=c("a","b",NA,NA,NA,"c"),c=c(1,1,1,1,2,NA),d=c("a","a","c",NA,NA,"b"))

fun_rep_na = function(df){
  for(i in colnames(df)){
    j<-sym(i)
    df = df %>% mutate(!!j=if_else(is.na(!!j),median(!!j, na.rm=TRUE),!!j))
  }
}

Я вижу, что в tidyr есть функция replace_na, но я тоже не знаю, как ее использовать. Во всяком случае, я бы хотел кастомную функцию.

Приведенный выше код дает мне ошибку.


person Helen    schedule 19.06.2019    source источник
comment
Вам не нужно использовать цикл for mutate_all. Кстати, median нужен числовой столбец   -  person akrun    schedule 19.06.2019
comment
Как рассчитать медианные значения factor и character столбцов?   -  person Ronak Shah    schedule 19.06.2019
comment
@akrun: Ах, отлично, спасибо, я этого не знал ‹3 Но как мне тогда указать, чем заменить? Я знаю о медиане фактора, но я бы хотел, чтобы в этом случае он заменил наиболее часто используемые значения. Извини, я бесполезен.   -  person Helen    schedule 19.06.2019
comment
@RonakShah: Я знаю, но медиана по определению является наиболее повторяемым значением, верно? :)   -  person Helen    schedule 19.06.2019
comment
Не очень разумно приписывать пропуски медианным значением (Allison, 2002), я настоятельно рекомендую проконсультироваться со статистиком.   -  person jay.sf    schedule 19.06.2019
comment
@ jay.sf: какая альтернатива?   -  person Helen    schedule 19.06.2019
comment
@Helen читать, например Эллисон, Пол Д. 2002. Отсутствующие данные. SAGE Publications, Inc.   -  person jay.sf    schedule 19.06.2019
comment
У меня нет времени покупать книгу прямо сейчас: /   -  person Helen    schedule 19.06.2019
comment
@ Хелен, потратьте немного денег и наймите статистика :)   -  person jay.sf    schedule 19.06.2019
comment
@ jay.sf: Я статистик.   -  person Helen    schedule 19.06.2019


Ответы (2)


Мы можем использовать mutate_if с median, поскольку median работает только с numeric столбцами

test %>% 
   mutate_if(is.numeric, list(~ replace(., is.na(.), median(., na.rm = TRUE))))

Если мы хотим, чтобы значение повторялось чаще, тогда нам может понадобиться Mode

Mode <- function(x) {
  x <- x[!is.na(x)]
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}

Здесь впервые была обновлена ​​функция Mode

test %>% 
  mutate_all(list(~ replace(., is.na(.), Mode(.))))
#  a b c d
#1 1 a 1 a
#2 2 b 1 a
#3 3 a 1 c
#4 4 a 1 a
#5 5 a 2 a
#6 6 c 1 b
person akrun    schedule 19.06.2019
comment
Ах, это выглядит красиво. Не могли бы вы объяснить, что делает ~ и все точки? - person Helen; 19.06.2019
comment
@Helen Это оператор тильды, используемый для краткости вызова анонимной функции в tidyverse, в противном случае вам может понадобиться function(x) replace(x, is.na(x), - person akrun; 19.06.2019
comment
Что такое анонимная функция и что является кратким? Не могли бы вы указать мне правильное направление, где об этом можно прочитать? - person Helen; 19.06.2019
comment
@Helen Анонимная функция используется во многих языках (иногда ее называют функцией lambda). Например, с python это будет lambda x: x * 5 или с использованием R, lapply(1:5, function(x) x: (x + 5)). Если вы проверили map и другие функции, краткость будет map(1:5, ~ .x:(.x + 5)) - person akrun; 19.06.2019

Я думаю, вы ищете Mode, а не медианное значение

Использование функции Mode из здесь

Mode <- function(x) {
   ux <- unique(x)
   ux[which.max(tabulate(match(x, ux)))]
}

library(dplyr)

test %>%  mutate_all(~replace(., is.na(.), Mode(na.omit(.))))

#  a b c d
#1 1 a 1 a
#2 2 b 1 a
#3 3 a 1 c
#4 4 a 1 a
#5 5 a 2 a
#6 6 c 1 b
person Ronak Shah    schedule 19.06.2019