报告data.frame中缺失值的优雅方法


80

这是我编写的一小段代码,用于报告数据框中缺少值的变量。我正在尝试一种更优雅的方式来执行此操作,该方法可能返回一个data.frame,但我遇到了麻烦:

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

编辑:我正在处理具有数十到数百个变量的data.frames,所以关键是我们只报告缺少值的变量。


@kohske:这是我的第一个想法,但是结果是个table字符,您必须解析出NA的数量。
约书亚·乌尔里希

自您发布答案以来,我正在回复您的问题。如果您想对答案发表评论,请作为对该答案的评论。如果问题也包含答案,这将变得非常混乱。
Andrie

@Andrie:我不同意您的编辑,因为我面临的一个关键问题是仅报告缺少值的变量。此外,您的回滚删除了我对代码所做的更改。我已经对问题进行了编辑以包含此信息,并在注释中添加了我对乔什代码的修改版本。
Zach

@Zach您的新编辑对我来说很好。顺便说一句,如果这可以澄清问题,我不反对在问题中添加其他数据/请求。
安德里(Andrie)

有五百万种方法可以执行此操作,请参阅CRAN任务视图
-MissingData

Answers:


155

只需使用 sapply

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

您也可以在由创建的矩阵上使用applycolSumsis.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 

11
我稍微修改了您的代码,只报告了缺失值:M <- sapply(airquality, function(x) sum(is.na(x))); M[M>0]
Zach

谢谢!学到了很多。
家蚕2015年

@Joshua Ulrich,您好,非常感谢您提供简洁的代码。我想在数据框中添加一列,以显示na值的百分比。您能为此提供一些帮助吗?
DukeLover

2
@Zach我使用您建议的一种形式来检查必填字段是否具有值:M <- colSums(is.na(airquality)); M[M <= 0]
Anthony Simon Mielniczuk

@Joshua为%s添加一个选项也是王牌!
radek

8

我们可以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

1
map_dfover的优点是sapply什么?
扎克

1
@Zach我认为没有太大区别,但是Hadley说不要在函数内使用sapply()。请参阅异常和调试·Advanced R. adv-r.had.co.nz/Exceptions-Debugging.html
Keiku

对于像我这样的懒惰的人,您可以使用较短的函数(〜)的purrr语法编写以上代码,因此看起来像这样:map_df( air quality, ~sum(is.na(.) )
Agile Bean,

1
@Zach的优势map_dfsapply只有当结果有很多行作为map_df的输出格式始终是一个tibble。
敏捷豆

1
@Zach:最好使用vapplyvs sapplyin函数,因为vapply它为您提供了一个已知的结果结构(您指定的)。sapply可能会返回数组或列表,具体取决于函数输出。的缺点map_df是您给它一个data.frame作为输入,并且它返回一个data.frame子类,而不是data.frame。不能保证小动作会像data.frame一样,将来在所有必要的情况下都会如此。
约书亚·乌尔里希

8

我最喜欢(不太宽的)数据的是出色的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)

在此处输入图片说明

这些示例来自包装插图,其中列出了其他有趣的可视化效果。


2
感谢您发布!现在gg_miss_upset()最新版本中有一个专用功能,一旦他们放假回来,它将提交给CRAN。naniar.njtierney.com/reference/gg_miss_upset.html
Nick Tierney

6
summary(airquality)

已经给你这个信息

VIM包还提供了一些不错的失踪data.frame数据图

library("VIM")
aggr(airquality)

在此处输入图片说明


VIM软件包可以报告哪些特定观测值缺少数据吗?
Anthony Simon Mielniczuk '16

别这么认为..但是您可以轻松地做到这一点(您必须用自己的数据框替换空气质量):res <-airquality [rowSums(is.na(airquality))> 0,]
Steffen Moritz

4

更简洁: sum(is.na(x[1]))

那是

  1. x[1] 看第一列

  2. is.na() 如果是,则为真 NA

  3. sum() TRUE1FALSE0


这不能回答原始问题,即查找数据中所有列的NAs的数量
Ben Bolker 2015年

4

另一个图形替代方案-plot_missing出色的DataExplorer包装功能:

在此处输入图片说明

Docs还指出了一个事实,您可以使用保存该结果以进行进一步分析missing_data <- plot_missing(data)


包中的plot_missing()功能DataExplorer现在是PlotMissing()
coip

1
@coipPlotMissing()已过时。请plot_missing()改用。有关更多详细信息,请参见#49
Boxuan

2

可以帮助您查看丢失数据的另一个函数是funModeling库中的df_status

library(funModeling)

iris.2是带有某些NA的虹膜数据集。您可以将其替换为数据集。

df_status(iris.2)

这将为您提供每列中NA的数量和百分比。


1

对于另一种图形解决方案,visdat 提供了vis_miss

library(visdat)
vis_miss(airquality)

在此处输入图片说明

Amelia输出非常相似,但开箱即用的缺失会产生%s,差异很小。


1

我认为Amelia库在处理丢失数据方面做得很好,还包括用于可视化丢失行的地图。

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

在此处输入图片说明

您还可以运行以下代码,将返回na的逻辑值

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

1

另一个图形和互动的方式是使用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"))

在此处输入图片说明

大型数据集可能无法很好地工作。


0

如果要对特定列进行操作,则也可以使用此方法

length(which(is.na(airquality[1])==T))

4
您无需将逻辑向量与T进行比较。您还可以通过对逻辑向量求和来计算TRUE元素的数量。
Houshalter


0

一种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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.