Ich möchte Zeilen aus einem data.frame entfernen, in dem alle Spalten NA sind. Aber ich möchte Zeilen behalten, die einige Werte NA haben.

Ich weiß, wie man das mit Base R macht, aber ich versuche herauszufinden, wie es mit tidyverse funktioniert. Ich versuche den Operator across.

library(tidyverse)

teste <- data.frame(a = c(1,NA,3, NA), b = c(NA, NA, 3, 4), c = c(1, NA, 3, 4))

teste
#>    a  b  c
#> 1  1 NA  1
#> 2 NA NA NA
#> 3  3  3  3
#> 4 NA  4  4
# I whant to remove rows where all values are NA
# that is, remove only line 2

# here I can get the lines with all values NA
teste %>%
  filter(across(a:c, is.na))
#>    a  b  c
#> 1 NA NA NA

# If I negate the filter, it does not work
# the last line (NA, 4, 4) is missing
teste %>%
  filter(!across(a:c, is.na))
#>   a  b c
#> 1 1 NA 1
#> 2 3  3 3

# This is what I'm expecting
# a  b  c
# 1 NA  1
# 3  3  3
# NA  4  4

# Using base I can do this with
teste[apply(teste, 1, function(x) sum(is.na(x))) < 3,]
#>    a  b c
#> 1  1 NA 1
#> 3  3  3 3
#> 4 NA  4 4

Wie kann ich das mit tidyverse machen?

Erstellt am 18.08.2018 durch das reprex-Paket (v0.3.0)

3
Daniel 19 Aug. 2020 im 03:21

3 Antworten

Beste Antwort

Wir können base R verwenden

teste[rowSums(!is.na(teste)) >0,]
#   a  b c
#1  1 NA 1
#3  3  3 3
#4 NA  4 4

Oder verwenden Sie apply und any

teste[apply(!is.na(teste), 1, any),]

Dies kann auch in filter verwendet werden.

teste %>%
      filter(rowSums(!is.na(.)) >0)

Oder mit c_across aus dplyr können wir die Zeilen direkt mit all NA entfernen

library(dplyr)
teste %>% 
    rowwise %>% 
    filter(!all(is.na(c_across(everything()))))
# A tibble: 3 x 3
# Rowwise: 
#      a     b     c
#  <dbl> <dbl> <dbl>
#1     1    NA     1
#2     3     3     3
#3    NA     4     4

HINWEIS: filter_all wird veraltet

2
akrun 19 Aug. 2020 im 00:27

Mit data.table können Sie das gleiche Ergebnis erzielen.

teste2 <- teste[-which(is.na(teste$a)&is.na(teste$b)&is.na(teste$c)),]
1
sunshinegirl 19 Aug. 2020 im 00:35

Zuvor konnten Sie in dplyr filter_all (für alle Spalten) / filter_at (für bestimmte Spalten) mit any_vars verwenden:

library(dplyr)

teste %>% filter_all(any_vars(!is.na(.)))

across hat jedoch keinen direkten Ersatz für any_vars, sodass Sie dies mit Reduce verwenden können:

teste %>% filter(Reduce(`|`, across(.fns = Negate(is.na))))
#   a  b c
#1  1 NA 1
#2  3  3 3
#3 NA  4 4
2
Ronak Shah 19 Aug. 2020 im 00:27