filtering off rows in a dataset using specific conditions

Viewed 44

I have a small follow-up question to a previous one answered here. With a dummy dataset as included below, I would like to filter off rows in which one or more of the samples (denoted S1, S2, S3, S4 in the dataset) has only "1" and "0", as well as all rows where the samples have only 1", "0" and "."

ID Pos S1 S2 S3 S4
A 22 . 1 0 .
B 21 1 0 . 1
C 50 0 . . .
D 11 . 1 . .
E 13 0 0 0 0
F 14 1 1 1 1
G 10 1 0 0 0

In other words, I want to keep only those rows that either has "1" in all the samples, or "0" in all samples, or "1" and "." in all samples, or lastly those with "0" and "." such that at the end, I have the final dataset looking as below

ID Pos S1 S2 S3 S4
C 50 0 . . .
D 11 . 1 . .
E 13 0 0 0 0
F 14 1 1 1 1

I am trying to do this in R and I request any suggestions from you.

Thanks and regards!

3 Answers

You can also use the following solution:

library(dplyr)
library(purrr)

df %>% 
  filter(pmap_lgl(., ~ { x <- c(...)[-c(1, 2)];
  !all(c(".", "0", "1") %in% x) & !all(c("0", "1") %in% x)}))

  ID Pos S1 S2 S3 S4
1  C  50  0  .  .  .
2  D  11  .  1  .  .
3  E  13  0  0  0  0
4  F  14  1  1  1  1

Keep rows where all values within S columns are different from "0" or "1" and have at least one "1" or "0" (to remove rows with only ".").

library(data.table)
library(purrr)

setDT(df)[
  pmap_lgl(
    mget(str_subset(names(df), "^S[0-9]+$")), 
    ~(all(c(...) != "1") || all(c(...) != "0")) && any(c(...) != ".")
  )
]

   ID Pos S1 S2 S3 S4
1:  C  50  0  .  .  .
2:  D  11  .  1  .  .
3:  E  13  0  0  0  0
4:  F  14  1  1  1  1

dieveed, it's best if you provide your data with R's dput function.

The way to do this in the tidyverse would be something like this:

library(dplyr)

df <- structure(list(ID = c("A", "B", "C", "D", "E", "F", "G"), Pos = c("22", 
"21", "50", "11", "13", "14", "10"), S1 = c(".", "1", "0", ".", 
"0", "1", "1"), S2 = c("1", "0", ".", "1", "0", "1", "0"), S3 = c("0", 
".", ".", ".", "0", "1", "0"), S4 = c(".", "1", ".", ".", "0", 
"1", "0")), row.names = c(NA, -7L), class = c("tbl_df", "tbl", 
"data.frame"))

df %>%
  filter(
    if_all(matches("^S"), ~ . == 0) |
      if_all(matches("^S"), ~ . == 1) |
      if_all(matches("^S"), ~ . != 0) |
      if_all(matches("^S"), ~ . != 1)
    )

# A tibble: 4 x 6
  ID    Pos   S1    S2    S3    S4   
  <chr> <chr> <chr> <chr> <chr> <chr>
1 C     50    0     .     .     .    
2 D     11    .     1     .     .    
3 E     13    0     0     0     0    
4 F     14    1     1     1     1   


Related