【问题标题】:Elegant way to report missing values in a data.frame报告 data.frame 中缺失值的优雅方式
【发布时间】:2012-01-09 04:11:26
【问题描述】:

这是我编写的一小段代码,用于报告数据框中缺少值的变量。我正在尝试一种更优雅的方法来执行此操作,可能会返回一个 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:我不同意您的编辑,因为我面临的一个关键问题是仅报告具有缺失值的变量。此外,您的回滚删除了我对代码所做的更改。我编辑了我的问题以包含这些信息,并将我修改后的 Josh 代码添加到评论中。
  • @Zach 您的新编辑对我来说看起来不错。顺便说一句,如果这能澄清问题,我不反对在问题上线后添加额外的数据/请求。
  • 有 50 万种方法可以做到这一点,请参阅 CRAN Task View - MissingData

标签: r dataframe missing-data


【解决方案1】:

对于管道,你可以写:

# Counts 
df %>% is.na() %>% colSums()

# % of missing rounded to 2 decimals 
df %>% summarise_all(.funs = ~round(100*sum(is.na(.))/length(.),2)) 

【讨论】:

    【解决方案2】:

    获取计数的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
    

    【讨论】:

      【解决方案3】:

      ExPanDaR的封装函数prepare_missing_values_graph可用于面板数据探索:

      【讨论】:

        【解决方案4】:

        另一种图形和交互方式是使用heatmaply库中的is.na10函数:

        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"))
        

        可能不适用于大型数据集..

        【讨论】:

          【解决方案5】:

          我最喜欢的(不太宽的)数据是来自优秀的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,其中列出了其他有趣的可视化。

          【讨论】:

          【解决方案6】:
          summary(airquality)
          

          已经给你这个信息

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

          library("VIM")
          aggr(airquality)
          

          【讨论】:

          • VIM 包能否报告哪些具体观察数据缺失?
          • 不这么认为.. 但你可以很容易地做到这一点(你必须用你自己的数据框替换空气质量): res 0,]
          【解决方案7】:

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

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

          你也可以运行下面的代码会返回na的逻辑值

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

          【讨论】:

            【解决方案8】:

            如需更多图形解决方案,visdatpackage 提供vis_miss

            library(visdat)
            vis_miss(airquality)
            

            Amelia 输出非常相似,只是在开箱即用时给出 %s 的细微差别。

            【讨论】:

              【解决方案9】:

              另一个图形替代方案 - 来自优秀 DataExplorer 包的 plot_missing 函数:

              Docs 还指出您可以使用missing_data &lt;- plot_missing(data) 保存此结果以进行进一步分析。

              【讨论】:

              • DataExplorer 包中的plot_missing() 函数现在是PlotMissing()
              • @coip PlotMissing() 已弃用。请改用plot_missing()。有关详细信息,请参阅#49
              【解决方案10】:

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

              library(funModeling)
              

              iris.2 是添加了一些 NA 的 iris 数据集。您可以将其替换为您的数据集。

              df_status(iris.2)
              

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

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                • map_dfsapply 有什么优势?
                • @Zach 我认为没有太大区别,但哈德利说不要在函数内部使用 sapply() 。请参阅异常和调试·高级 R.adv-r.had.co.nz/Exceptions-Debugging.html
                • 对于像我这样的懒人,你可以用更短的 purrr 语法为函数 (~) 编写上面的代码,所以它看起来像这样:map_df( air quality, ~sum(is.na(.) )
                • @Zach map_df 相对于sapply 的优势仅在于结果有很多行时,因为 map_df 的输出格式始终是 tibble。
                • @Zach:最好在函数中使用vapplysapply,因为vapply 为您提供了一个已知的结果结构(您可以指定)。 sapply 可能会返回数组或列表,具体取决于函数输出。 map_df 的一个缺点是你给它一个 data.frame 作为输入,它返回一个 data.frame 子类,而不是一个 data.frame。无法保证 tibbles 在未来所有必要的情况下都会像 data.frames 那样表现。
                【解决方案12】:

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

                那是

                1. x[1]看第一列

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

                3. sum()TRUE1FALSE0

                【讨论】:

                • 这并没有回答原来的问题,即为数据中的所有列查找NAs的数量
                【解决方案13】:

                如果你想为特定的列做,那么你也可以使用这个

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

                【讨论】:

                • 你不需要将逻辑向量与T进行比较。你也可以通过求和来计算逻辑向量中TRUE元素的数量。
                【解决方案14】:

                只需使用sapply

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

                您还可以在is.na() 创建的矩阵上使用applycolSums

                > 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 
                

                【讨论】:

                • 我稍微修改了你的代码,只报告缺失值:M &lt;- sapply(airquality, function(x) sum(is.na(x))); M[M&gt;0]
                • 谢谢!学到了很多。
                • 嗨@Joshua Ulrich,非常感谢您简洁的代码。我想在数据框中添加一列,显示 na 值的百分比。你能提供一些帮助吗?
                • @Zach 我使用您的建议版本来检查必填字段是否具有值:M &lt;- colSums(is.na(airquality)); M[M &lt;= 0]
                • @Joshua 为 %s 添加一个选项也是王牌!
                猜你喜欢
                • 1970-01-01
                • 2015-09-19
                • 1970-01-01
                • 2019-06-08
                • 2011-10-03
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-11-04
                相关资源
                最近更新 更多