【问题标题】:Remove rows with "NA" if present in all column如果存在于所有列中,则删除带有“NA”的行
【发布时间】:2019-08-16 21:20:18
【问题描述】:

嗨,我的数据框由所有列中都有 NA 的行组成,我想删除它们。

这是我的数据框示例的样子:

Date       Blk 3    Blk 3    Blk3     Total
           Lvl 2-25 Lvl 2-26 Lvl 2-27 
2019-01-02  1       20       10        31
2019-01-02  NA      NA       NA        NA
2019-01-03  NA      10       30        40

我只想删除第二行。并在删除后看起来像这样:

Date       Blk 3    Blk 3    Blk3     Total
           Lvl 2-25 Lvl 2-26 Lvl 2-27 
2019-01-02  1       20       10        31
2019-01-03  NA      10       30        40

我试过这样的方法:

df <- df %>% remove_empty("rows") #using janitor package

df <- df %>% filter_all(any_vars(!is.na(.)))
df <- df %>% filter_all(any_vars(complete.cases(.))) 

df <- df[rowSums(is.na(df)) != ncol(df), ]

但它们都不起作用。有人可以帮帮我吗?

这是我的输入(df):

structure(list(Date = structure(c(17777, 17778, 17779, 17780, 
17781, 17782), class = "Date"), `Blk 3 Lvl 2-25` = c(300, 200, 
600, 600, 250, 800), `Blk 3 Lvl 2-26` = c(400, 120, 400, 3000, 
150, 1200), `Blk 3 Lvl 2-27` = c(500, 90, 120, 300, 800, 200), 
    `Blk 3 Lvl 2-28` = c(80, 800, 150, 500, 1500, 800), `Blk 3 Lvl 2-29` = c(50, 
    300, 1.2, 80, 120, 12), `Blk 3 Lvl 2-30` = c(150, 30, 60, 
    300, 1500, NA), `Blk 3 Lvl 2-31` = c(30, 600, 400, 2000, 
    250, NA), `Blk 3 Lvl 2-32` = c(2000, 3000, 600, 1200, 900, 
    NA), `Blk 3 Lvl 2-33` = c(250, 200, 200, 150, 250, NA), `Blk 3 Lvl 2-34` = c(1500, 
    5000, 1.2, 3000, 600, NA), `Blk 3 Lvl 2-35` = c(2000, 1500, 
    1500, 3000, 1500, NA), `Blk 3 Lvl 2-36` = c(1500, 1500, 1500, 
    2000, 1500, NA), `Blk 3 Lvl 2-37` = c(400, 800, 3000, 600, 
    1200, NA), `Blk 3 Lvl 2-38` = c(600, 1200, 1200, 2000, 800, 
    NA), `Blk 3 Lvl 5-25` = c(2000, 1200, 900, 3000, 900, NA), 
    `Blk 3 Lvl 5-26` = c(200, 200, 1.2, 400, 600, NA), `Blk 3 Lvl 5-27` = c(800, 
    800, 600, 800, 400, NA), `Blk 3 Lvl 5-28` = c(800, 800, 1.2, 
    800, 2000, NA), `Blk 3 Lvl 5-29` = c(1200, 1200, 800, 600, 
    900, NA), `Blk 3 Lvl 5-30` = c(1500, 1200, 900, 400, 1200, 
    NA), `Blk 3 Lvl 5-31` = c(400, 800, 1.2, 12, 90, NA), `Blk 3 Lvl 5-32` = c(150, 
    120, 200, 300, 150, NA), `Blk 3 Lvl 5-33` = c(500, 600, 900, 
    300, 900, NA), `Blk 3 Lvl 5-34` = c(300, 300, 1.2, 900, 1200, 
    NA), `Blk 3 Lvl 5-35` = c(200, 250, 300, 200, 200, NA), `Blk 3 Lvl 5-36` = c(900, 
    1200, 3000, 2000, 1500, NA), `Blk 3 Lvl 5-37` = c(800, 1500, 
    2000, 2000, 3000, NA), `Blk 3 Lvl 5-38` = c(600, 200, 3000, 
    80, 400, NA), `Blk 3 Lvl 7-25` = c(900, 400, 1200, 800, 400, 
    NA), `Blk 3 Lvl 7-26` = c(1500, 800, 3000, 800, 600, NA), 
    `Blk 3 Lvl 7-27` = c(800, 400, 300, 400, 400, NA), `Blk 3 Lvl 7-28` = c(200, 
    200, 200, 30, 12, NA), `Blk 3 Lvl 7-29` = c(NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-30` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-31` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-32` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-33` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-34` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-35` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-36` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-37` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `Blk 3 Lvl 7-38` = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), Total = c(23510, 
    27510, 27037.2, 32552, 26172, 3012)), row.names = c(NA, 6L
), class = "data.frame")

这是我的实际数据框的样子,我想删除像第 7 行这样的行:

【问题讨论】:

  • 由于您不想计算第一列的 NA 值,您需要执行 df[rowSums(is.na(df)) != ncol(df) - 1, ] 或使用 dplyr, df %&gt;% filter_at(vars(starts_with("Lv")), any_vars(!is.na(.)))
  • @RonakShah 嗨,谢谢您的快速回复,但是在我尝试之后没有任何改变
  • 您是否将结果分配回去? df1 &lt;- df[rowSums(is.na(df)) != ncol(df) - 1, ]。立即查看df1
  • 截图不会有帮助。如果数据框很大,您只能添加 dput(head(df))
  • 基于您共享的dput,没有任何行具有NA 的所有值,因此不会删除任何行您要删除哪一行?

标签: r dataframe


【解决方案1】:

问题是在计算NA 值时需要排除超过 1 列。我们可以只选择我们需要的列并执行rowSums

cols <- grep("^Blk", names(df))
df[rowSums(is.na(df[cols])) != length(cols), ]

或者使用dplyr 会是

library(dplyr)
df %>% filter_at(vars(starts_with("Blk")), any_vars(!is.na(.)))

【讨论】:

    【解决方案2】:

    base R 中的一个选项是选择感兴趣的列 ('nm1'),使用 lapply 循环遍历列,检查它们是否为 NA 以转换为逻辑向量,Reduce 将其转换为单个逻辑带有&amp; 的向量,否定 (!) 并对行进行子集化

    nm1 <- grep("^Blk", names(df))
    df[!Reduce(`&`, lapply(df[nm1], is.na)),]
    

    也可以用rowSums完成

    df[rowSums(!is.na(df[nm1])) > 0,]
    

    【讨论】:

      猜你喜欢
      • 2021-04-17
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 2018-10-21
      • 2021-08-25
      相关资源
      最近更新 更多