Елегантен начин за докладване на липсващи стойности в data.frame

Ето малка част от кода, който написах, за да докладвам променливи с липсващи стойности от рамка с данни. Опитвам се да измисля по-елегантен начин да направя това, който може би връща data.frame, но съм заседнал:

for (Var in names(airquality)) {
    missing <- sum(is.na(airquality[,Var]))
    if (missing > 0) {
        print(c(Var,missing))
    }
}

Редактиране: Имам работа с data.frames с десетки до стотици променливи, така че е от ключово значение да докладваме само променливи с липсващи стойности.


person Zach    schedule 29.11.2011    source източник
comment
@kohske: това беше първата ми мисъл, но резултатите са table символи и ще трябва да анализирате броя на NA.   -  person Joshua Ulrich    schedule 30.11.2011
comment
Връщам въпроса ви, тъй като сте публикували отговор. Ако искате да коментирате отговор, моля, направете го като коментар към този отговор. Ако въпросите съдържат и отговори, това става много объркващо.   -  person Andrie    schedule 30.11.2011
comment
@Andrie: Не съм съгласен с вашата редакция, тъй като ключов проблем, пред който съм изправен, е отчитането само на променливи с липсващи стойности. Освен това вашето връщане назад премахна промяна, която направих в кода. Редактирах въпроса си, за да включва тази информация, и добавих модифицираната си версия на кода на Джош към коментар.   -  person Zach    schedule 30.11.2011
comment
@Zach Новата ви редакция ми изглежда добре. Не съм против добавянето на допълнителни данни/заявки във въпрос, след като е активен, между другото, ако това изяснява въпроса.   -  person Andrie    schedule 30.11.2011
comment
Има половин милион начина да направите това, вижте CRAN Task View - MissingData   -  person zx8754    schedule 20.05.2019


Отговори (13)


Просто използвайте sapply

> sapply(airquality, function(x) sum(is.na(x)))
  Ozone Solar.R    Wind    Temp   Month     Day 
     37       7       0       0       0       0

Можете също да използвате apply или colSums в матрицата, създадена от is.na()

> apply(is.na(airquality),2,sum)
  Ozone Solar.R    Wind    Temp   Month     Day 
     37       7       0       0       0       0
> colSums(is.na(airquality))
  Ozone Solar.R    Wind    Temp   Month     Day 
     37       7       0       0       0       0 
person Joshua Ulrich    schedule 29.11.2011
comment
Промених леко вашия код, за да докладвам само липсваща стойност: M <- sapply(airquality, function(x) sum(is.na(x))); M[M>0] - person Zach; 30.11.2011
comment
Благодаря! Научих много. - person Bombyx mori; 15.11.2015
comment
Здравейте @Joshua Ulrich, благодаря много за краткия ви код. Бих искал да добавя колона в рамката с данни, която да показва процента на стойностите на. Можете ли да предоставите малко помощ относно това? - person DukeLover; 17.06.2017
comment
@Zach Използвам версия на вашето предложение за проверка дали задължителните полета имат стойност: M <- colSums(is.na(airquality)); M[M <= 0] - person Anthony Simon Mielniczuk; 03.10.2017
comment
@Joshua добавянето на опция за %s също би било асо! - person radek; 30.05.2019

Новият ми фаворит за (не твърде широки) данни са методите от отличния пакет naniar. Не само получавате честоти, но и модели на липса:

library(naniar)
library(UpSetR)

riskfactors %>%
  as_shadow_upset() %>%
  upset()

въведете описание на изображението тук

Често е полезно да се види къде са липсващите по отношение на нелипсващите, което може да се постигне чрез начертаване на диаграмата на разсейване с липсващи:

ggplot(airquality,
       aes(x = Ozone,
           y = Solar.R)) +
 geom_miss_point()

въведете описание на изображението тук

Или за категорични променливи:

gg_miss_fct(x = riskfactors, fct = marital)

въведете описание на изображението тук

Тези примери са от пакет vignette, който изброява други интересни визуализации.

person radek    schedule 02.07.2018
comment
Благодаря, че публикувахте това! Вече има специална функция gg_miss_upset() в най-новата версия, която ще бъде изпратена на CRAN, след като се върнат от почивка.naniar.njtierney.com/reference/gg_miss_upset.html - person Nick Tierney; 10.09.2018

Можем да използваме map_df с purrr.

library(mice)
library(purrr)

# map_df with purrr
map_df(airquality, function(x) sum(is.na(x)))
# A tibble: 1 × 6
# Ozone Solar.R  Wind  Temp Month   Day
# <int>   <int> <int> <int> <int> <int>
# 1    37       7     0     0     0     0
person Keiku    schedule 27.01.2017
comment
Какво е предимството на map_df пред sapply? - person Zach; 27.01.2017
comment
@Zach Мисля, че няма голяма разлика, но Хадли каза да не се използва sapply() във функция. Вижте Изключения и отстраняване на грешки · Разширено R. adv-r.had.co.nz/ Exceptions-Debugging.html. - person Keiku; 27.01.2017
comment
за мързеливи хора като мен, можете да напишете горния код в по-кратък purrr синтаксис за функции (~), така че да изглежда така: map_df( air quality, ~sum(is.na(.) ) - person Agile Bean; 29.01.2019
comment
@Zach предимството на map_df пред sapply е само когато резултатът има много редове, тъй като изходният формат на map_df винаги е тибъл. - person Agile Bean; 29.01.2019
comment
@Zach: по-добре е да използвате vapply срещу sapply във функции, защото vapply ви дава известна структура на резултата (която посочвате). sapply може да върне масив или списък, в зависимост от изхода на функцията. Недостатък на map_df е, че му давате data.frame като вход и той връща подклас data.frame, а не data.frame. Няма гаранция, че tibbles ще се държат като data.frames във всички необходими случаи в бъдеще. - person Joshua Ulrich; 30.05.2019

summary(airquality)

вече ви дава тази информация

Пакетите VIM също предлагат някои хубави диаграми на липсващи данни за data.frame

library("VIM")
aggr(airquality)

въведете описание на изображението тук

person Steffen Moritz    schedule 10.11.2016
comment
Може ли пакетът VIM да докладва за кои конкретни наблюдения липсват данни? - person Anthony Simon Mielniczuk; 17.11.2016
comment
не мисля така.. но можете да получите това доста лесно (ще трябва да замените airquality с ваша собствена рамка от данни): res ‹- airquality[rowSums(is.na(airquality)) › 0,] - person Steffen Moritz; 18.11.2016

По-кратко-: sum(is.na(x[1]))

Това е

  1. x[1] Погледнете първата колона

  2. is.na() вярно, ако е NA

  3. sum() TRUE is 1, FALSE is 0

person Keith Whittingham    schedule 11.04.2015
comment
това не отговаря на първоначалния въпрос, който е да се намери броят на NAs за всички колони в данните - person Ben Bolker; 11.04.2015

Друга графична алтернатива - plot_missing функция от отличен DataExplorer пакет:

въведете описание на изображението тук

Документи също посочват факта, че можете да запазите тези резултати за допълнителен анализ с missing_data <- plot_missing(data).

person radek    schedule 13.02.2018
comment
Функцията plot_missing() в пакета DataExplorer вече е PlotMissing(). - person coip; 07.03.2018
comment
@coip PlotMissing() е отхвърлен. Моля, използвайте plot_missing() вместо това. Вижте #49 за повече подробности. - person Boxuan; 02.08.2018

Друга функция, която би ви помогнала да разгледате липсващите данни, е df_status от библиотеката funModeling

library(funModeling)

iris.2 е наборът от данни за ириса с някои добавени NA. Можете да замените това с вашия набор от данни.

df_status(iris.2)

Това ще ви даде броя и процента на NA във всяка колона.

person Shahan Degamwala    schedule 06.02.2017

За още едно графично решение visdat пакет предлага vis_miss.

library(visdat)
vis_miss(airquality)

въведете описание на изображението тук

Много подобен на Amelia изход с малка разлика в даването на %s при липсващи данни извън кутията.

person radek    schedule 03.12.2017

Мисля, че библиотеката Amelia върши добра работа при обработката на липсващи данни, също така включва карта за визуализиране на липсващите редове.

install.packages("Amelia")
library(Amelia)
missmap(airquality)

въведете описание на изображението тук

Можете също да изпълните следния код, който ще върне логическите стойности на na

row.has.na <- apply(training, 1, function(x){any(is.na(x))})
person drexxx    schedule 19.04.2017

Друг графичен и интерактивен начин е да използвате is.na10 функция от heatmaply библиотека:

library(heatmaply)

heatmaply(is.na10(airquality), grid_gap = 1, 
          showticklabels = c(T,F),
            k_col =3, k_row = 3,
            margins = c(55, 30), 
            colors = c("grey80", "grey20"))

въведете описание на изображението тук

Вероятно няма да работи добре с големи набори от данни..

person radek    schedule 27.08.2018

Ако искате да го направите за определена колона, можете също да използвате това

length(which(is.na(airquality[1])==T))
person Chintak Chhapia    schedule 09.06.2014
comment
Не е необходимо да сравнявате логически вектор с T. Можете също така да преброите броя на TRUE елементите в логически вектор, като го сумирате. - person Houshalter; 01.12.2014

Пакетната функция на ExPanDaR prepare_missing_values_graph може да се използва за изследване на данните от панела:

въведете описание на изображението тук

person radek    schedule 05.04.2019

dplyr Решение за получаване на броя може да бъде:

summarise_all(df, ~sum(is.na(.)))

Или за да получите процент:

summarise_all(df, ~(sum(is_missing(.) / nrow(df))))

Може би също така си струва да се отбележи, че липсващите данни могат да бъдат грозни, непоследователни и не винаги кодирани като NA в зависимост от източника или начина, по който се обработват при импортиране. Следната функция може да бъде променена в зависимост от вашите данни и това, което искате да считате за липсващо:

is_missing <- function(x){
  missing_strs <- c('', 'null', 'na', 'nan', 'inf', '-inf', '-9', 'unknown', 'missing')
  ifelse((is.na(x) | is.nan(x) | is.infinite(x)), TRUE,
         ifelse(trimws(tolower(x)) %in% missing_strs, TRUE, FALSE))
}

# sample ugly data
df <- data.frame(a = c(NA, '1', '  ', 'missing'),
                 b = c(0, 2, NaN, 4),
                 c = c('NA', 'b', '-9', 'null'),
                 d = 1:4,
                 e = c(1, Inf, -Inf, 0))

# counts:
> summarise_all(df, ~sum(is_missing(.)))
  a b c d e
1 3 1 3 0 2

# percentage:
> summarise_all(df, ~(sum(is_missing(.) / nrow(df))))
     a    b    c d   e
1 0.75 0.25 0.75 0 0.5
person sbha    schedule 14.03.2020