2

I want to remove all the rows having either zeros or NAs. In the code below I am selecting numeric variables and then filtering out 0s. Problem here is it does not return character variables along with numeric ones in the final output.

df <- read.table(header = TRUE, text = 
                   "x   y   z
a   1   2
b   0   3
c   1   NA
d 0 NA
")

df %>% select_if(is.numeric) %>% filter(rowSums(., na.rm = T)!=0)
Ric S
  • 9,073
  • 3
  • 25
  • 51
john
  • 1,026
  • 8
  • 19

4 Answers4

2

You can use filter_if :

library(dplyr)
df %>% filter_if(is.numeric, any_vars(. != 0 & !is.na(.)))

#  x y  z
#1 a 1  2
#2 b 0  3
#3 c 1 NA

Or using base R :

cols <- sapply(df, is.numeric)
df[rowSums(!is.na(df[cols]) & df[cols] != 0) > 0, ]
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
2

Another dplyr option could be:

df %>%
 rowwise() %>%
 filter(any(across(where(is.numeric)) != 0, na.rm = TRUE))

  x         y     z
  <fct> <int> <int>
1 a         1     2
2 b         0     3
3 c         1    NA
tmfmnk
  • 38,881
  • 4
  • 47
  • 67
0

Following the suggestions written in this new doc page after the release of dplyr version 1.0.0, you can create a helper function to substitute the superseded functions filter_if and any_vars.

Previously, filter() was paired with the all_vars() and any_vars() helpers. Now, across() is equivalent to all_vars(), and there’s no direct replacement for any_vars(). However you can make a simple helper yourself

From now on, this way should be the reference method for this kind of filtering steps.

rowAny <- function(x) {rowSums(x != 0 & !is.na(x)) > 0}
df %>% filter(rowAny(across(where(is.numeric))))

#   x y  z
# 1 a 1  2
# 2 b 0  3
# 3 c 1 NA
Ric S
  • 9,073
  • 3
  • 25
  • 51
0

You could simply do

df[rowSums(suppressWarnings(sapply(df, as.double)), na.rm=TRUE) > 0, ]
#   x y  z
# 1 a 1  2
# 2 b 0  3
# 3 c 1 NA
jay.sf
  • 60,139
  • 8
  • 53
  • 110