Keep rows that match a condition

filter()

SAS: WHERE, subsetting IF

dplyr::filter() keeps rows for which the condition is TRUE.

Quick reference

library(dplyr)

df |>
  filter(PARAMCD == "SYSBP")

df |>
  filter(PARAMCD == "SYSBP", !is.na(AVAL))
R SAS
filter(cond) where cond; or subsetting if cond;
filter(a, b) where a and b; (both must be true)
filter(a \| b) where a or b;

Traps: filter() keeps rows where the condition is TRUE. NA in the condition drops the row. SAS where aval < 100 keeps missing numeric rows (missing is smaller than any number). Use !is.na(AVAL) when missing must not pass.

Worked examples below.

One condition

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
vs <- data.frame(
  USUBJID = c("STD-001-0001", "STD-001-0001", "STD-001-0002"),
  PARAMCD = c("SYSBP", "DIABP", "SYSBP"),
  AVAL = c(120, 80, NA_real_)
)

vs |>
  filter(PARAMCD == "SYSBP")
       USUBJID PARAMCD AVAL
1 STD-001-0001   SYSBP  120
2 STD-001-0002   SYSBP   NA

SAS: where paramcd = "SYSBP";

Several conditions

vs |>
  filter(PARAMCD == "SYSBP", !is.na(AVAL))
       USUBJID PARAMCD AVAL
1 STD-001-0001   SYSBP  120

Commas in filter() mean AND. Use | for OR. !is.na(AVAL) is the usual way to drop missing results before a comparison.

Missing numeric: SAS WHERE keeps the row

Same table. Compare AVAL < 100 in both languages.

vs |>
  filter(AVAL < 100)
       USUBJID PARAMCD AVAL
1 STD-001-0001   DIABP   80
AVAL SAS where aval < 100 R filter(AVAL < 100)
120 drop drop
80 keep keep
missing keep drop

R keeps only 80. NA < 100 is NA, not TRUE, so filter() drops that row.

SAS where aval < 100; keeps 80 and the missing row. A missing numeric is smaller than any number, so the comparison is true.

To drop missing in R, say so:

vs |>
  filter(!is.na(AVAL), AVAL < 100)
       USUBJID PARAMCD AVAL
1 STD-001-0001   DIABP   80

To keep missing on purpose (the SAS WHERE result on this data):

vs |>
  filter(is.na(AVAL) | AVAL < 100)
       USUBJID PARAMCD AVAL
1 STD-001-0001   DIABP   80
2 STD-001-0002   SYSBP   NA
ImportantNA in the condition drops the row

filter(AVAL < 100) drops rows where AVAL is NA. SAS WHERE aval < 100 keeps them. Write !is.na(AVAL) when missing must not pass.