Эффективный способ вычисления строк, отличных от NA, по сравнению с строками NA в столбце

Я ищу способ эффективно и легко вычислить соотношение между значениями, отличными от NA, и значениями NA в столбце.

Как я знаю, это использование dplyr, код ниже

Data %>% count(filter(!is.na(x2012))) / count(filter(is.na(x2012)))

Есть ли способ попроще? Я думал, что n_unique в пакете dplyr может быть чем-то, но тогда, если у вас есть несколько идентичных наблюдений, соотношение будет неправильным.


person uncool    schedule 30.10.2015    source источник


Ответы (3)


Нет необходимости в конкретной функции, base R вы можете просто сделать:

colSums(is.na(df))/colSums(!is.na(df))
#  a   b   c 
#2.0 0.5 Inf

Для определенного набора столбцов:

colSums(is.na(df))/colSums(!is.na(df))  # works also with one value aka 'a'

Данные:

 df = data.frame(a=c(NA,NA,4),b=c(NA,1,2),c=c(NA,NA,NA))
person Colonel Beauvel    schedule 30.10.2015

Вы можете написать короткие вспомогательные функции для вычисления:

Соотношение значений, отличных от NA, к NA

(Он вернет Inf, если есть нулевые NA значения):

valid_ratio <- function(vec){
  sum(!is.na(vec)) / sum(is.na(vec))
}

Процент записей, не соответствующих критериям

(передает ту же информацию, легче интерпретировать):

perc_NA <- function(vec){
  sum(is.na(vec)) / length(vec)
}

Вы можете использовать их с summarise dplyr следующим образом:

mtcars %>%
  summarise(percent_NA = perc_NA(am))

  percent_NA
1          0

mtcars$am нет значений NA)

person Sam Firke    schedule 30.10.2015
comment
OP, похоже, хочет #notNA / #NA, а не процентное соотношение. - person Frank; 30.10.2015
comment
Хороший улов, хотя мне кажется, что это менее понятный способ кодирования той же информации. Он также вернет Inf вместо значений 0-1. - person Sam Firke; 30.10.2015
comment
Да, согласен, не очень хороший путь. Вы можете добавить этот пункт к ответу, если все еще включаете per_NA. - person Frank; 30.10.2015

count отлично работает:

data.frame(a=rep(c(1,NA),c(3,7))) %>% 
  count(     isNA  = is.na(a) ) %>% 
  summarise( ratio = n[!isNA] / n[isNA] )

      ratio
      (dbl)
1 0.4285714

Это соотношение 3/7, правильное для данных примера в первой строке.

person Frank    schedule 30.10.2015