【问题标题】:Remove rows containing NA from the column with the least number of NAs从 NA 数量最少的列中删除包含 NA 的行
【发布时间】:2019-09-13 05:46:59
【问题描述】:

我有一个最终将转换为xts 对象的数据框。第一列包含日期数据,而所有其他列包含数字数据。但是,并非所有数字列都具有相同数量的值/相同的长度。有些列包含的 NA 行比其他列多。

我想通过删除 NA 数量最少的列中包含 NA 的行来过滤我的数据框,但仍为我选择的所有其他列保留包含 NA 的行。例如,下面的列 grpA 的 NA 数量最少。我想删除包含 NA 的数据帧的前 2 行,但保留 grpB 中的值,无论它们是什么。

我有什么:

Date        grpA    grpB
2007-11-06  NA      NA
2007-11-07  NA      NA
2007-11-09  1.66    NA
2007-11-12  1.64    NA
2007-11-13  1.61    1.28
2007-11-14  1.60    1.30
2007-11-15  1.57    1.27
2007-11-16  1.56    1.25
2007-11-19  1.55    1.25
2007-11-20  1.55    1.25
2007-11-21  1.52    1.22
2007-11-22  1.50    1.21
2007-11-23  1.51    1.21
2007-11-26  1.52    1.25
2007-11-27  1.50    1.25
2007-11-28  1.50    1.23
2007-11-29  1.52    1.24
2007-11-30  1.56    1.25
2007-12-03  1.56    1.22
2007-12-04  1.56    1.23

我想要什么:

Date        grpA    grpB
2007-11-09  1.66    NA
2007-11-12  1.64    NA
2007-11-13  1.61    1.28
2007-11-14  1.60    1.30
2007-11-15  1.57    1.27
2007-11-16  1.56    1.25
2007-11-19  1.55    1.25
2007-11-20  1.55    1.25
2007-11-21  1.52    1.22
2007-11-22  1.50    1.21
2007-11-23  1.51    1.21
2007-11-26  1.52    1.25
2007-11-27  1.50    1.25
2007-11-28  1.50    1.23
2007-11-29  1.52    1.24
2007-11-30  1.56    1.25
2007-12-03  1.56    1.22
2007-12-04  1.56    1.23

数据帧的可重现样本如下:

df <- data.frame(Date = structure(c(1194307200, 1194393600, 1194566400, 
                                    1194825600, 1194912000, 1194998400, 1195084800, 1195171200, 1195430400, 
                                    1195516800, 1195603200, 1195689600, 1195776000, 1196035200, 1196121600, 
                                    1196208000, 1196294400, 1196380800, 1196640000, 1196726400), class = c("POSIXct", 
                                                                                                           "POSIXt"), tzone = "UTC"), 
                 grpA = c(NA, NA, 1.66, 1.64, 1.61, 1.6, 1.57, 1.56, 1.55, 1.55, 1.52, 1.5, 1.51, 1.52, 1.5, 1.5, 1.52, 1.56, 1.56, 1.56), 
                 grpB = c(NA, NA, NA, NA, 1.28, 1.3, 1.27, 1.25, 1.25, 1.25, 1.22, 1.21, 1.21, 1.25, 1.25, 1.23, 1.24, 1.25, 1.22, 1.23))

我已经尝试了 tidyr 包中的 drop_na 函数,它可以工作:

df2 <- drop_na(df, grpA)

但是,我将在 Shiny App 中使用上述过滤,并且我不会提前知道用户会选择哪些列中包含 NA 的行数最少。

我尝试了以下方法来识别其中包含 NA 的行数最少的列,但它为我提供了非 NA 行数而不是列名:

max(colSums(!is.na(df[-1])))

我尝试使用以下方法提取列名,但遇到错误:

colnames(df)[which(colSums(!is.na(df[-1]))) == max(colSums(!is.na(df[-1])))]

我认为这是一项简单的任务,但它变得相当复杂。我需要答案才能在闪亮的反应式表达式中使用。

谢谢,非常感谢!

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    我们可以先找到NAs 最少的列的名称,然后从该列中删除NA 行。

    col <- names(which.min(colSums(is.na(df[-1]))))
    df[!is.na(df[col]), ]
    
    
    #         Date grpA grpB
    #3  2007-11-09 1.66   NA
    #4  2007-11-12 1.64   NA
    #5  2007-11-13 1.61 1.28
    #6  2007-11-14 1.60 1.30
    #7  2007-11-15 1.57 1.27
    #8  2007-11-16 1.56 1.25
    #9  2007-11-19 1.55 1.25
    #10 2007-11-20 1.55 1.25
    #11 2007-11-21 1.52 1.22
    #12 2007-11-22 1.50 1.21
    #13 2007-11-23 1.51 1.21
    #14 2007-11-26 1.52 1.25
    #15 2007-11-27 1.50 1.25
    #16 2007-11-28 1.50 1.23
    #17 2007-11-29 1.52 1.24
    #18 2007-11-30 1.56 1.25
    #19 2007-12-03 1.56 1.22
    #20 2007-12-04 1.56 1.23
    

    这也可以在单行中完成,而无需创建额外的变量

    df[!is.na(df[names(which.min(colSums(is.na(df[-1]))))]), ]
    

    使用相同的逻辑 dplyr 方法可能是使用 filter_at

    library(dplyr)
    
    df %>%
       filter_at(df %>%
       summarise_at(-1, ~sum(is.na(.))) %>%
       which.min %>% names, ~!is.na(.))
    

    或与tidyr::drop_na一起使用

    tidyr::drop_na(df, df %>%
                      summarise_at(-1, ~sum(is.na(.))) %>%
                      which.min %>% names)
    

    【讨论】:

    • 我能有一个可以通过管道传输到 dplyr 的答案吗?我仍在努力将其集成到我的实际代码中。我的实际代码类似于 df %>% select(Date, input$varnames) 其中 input$varnames 来自selectizeInput,可能有多个值
    • @DTYK 不是shiny 专家,但我添加了dplyr 版本,检查它是否有帮助,是否可以通过某种方式进行整合。
    • 尝试了以下方法,但仍然无法正常工作:df %>% select(Date, input$varnames) %>% drop_na(., . %>% summarise_at(-1, ~sum(is .na(.))) %>% which.min %>% 个名字)
    • 什么是input$varnames?它为什么如此重要?那些是您要检查NA 值的列名吗?
    • input$varnames 是来自闪亮 UI 的输入,其中用户选择一个或多个变量/列。它作为具有 1 个或多个元素的字符向量读入到 select 语句中。提供的错误是“警告:错误:. %&gt;% summarise_at(-1, ~sum(is.na(.))) %&gt;% which.min %&gt;% names 必须计算为列位置或名称,而不是函数”
    猜你喜欢
    • 1970-01-01
    • 2012-10-12
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 2020-09-22
    相关资源
    最近更新 更多