Filter an R Data Frame with at Least N Non-NA Values per Row
When a data frame contains missing values, you may want to retain only the rows that have a minimum amount of usable data. For example, in a data frame with four columns, you can keep only rows containing at least two, three, or four non-NA values.
In base R, count the missing values in each row with rowSums(is.na(...)), or count the non-missing values directly with rowSums(!is.na(...)). Then use the resulting logical vector to subset the data frame.
Base R Syntax for Keeping Rows with at Least N Non-NA Values
To filter rows of a dataframe that has atleast N non-NAs, use dataframe subsetting as shown below
resultDF = mydataframe[rowSums(is.na(mydataframe[ , 0:ncol(mydataframe)])) <= (ncol(mydataframe) - N), ]
This expression counts the NA values in each row. A row is retained when its number of missing values is no greater than the total number of columns minus N.
An equivalent and more direct expression is to count non-missing values:
resultDF <- mydataframe[rowSums(!is.na(mydataframe)) >= N, ]
where
mydataframeis the data frame containing complete and missing values.Nis the minimum number of non-NAvalues required in each retained row.resultDFis the filtered data frame.
Example 1 – Filter R Dataframe with minimum N non-NAs
In this example, we will create a Dataframe containing rows with different number of NAs.
> mydataframe = data.frame(x = c(9, NA, 7, 4), y = c(4, NA, NA, 21), z = c(9, 8, NA, 74), p = c(NA, 63, NA, 2))
> mydataframe
x y z p
1 9 4 9 NA
2 NA NA 8 63
3 7 NA NA NA
4 4 21 74 2
Now, we will filter this dataframe such that the output contains only rows with atleast 2 non-NAs.
> N = 2
> resultDF = mydataframe[rowSums(is.na(mydataframe[ , 0:ncol(mydataframe)])) <= (ncol(mydataframe) - N), ]
> resultDF
x y z p
1 9 4 9 NA
2 NA NA 8 63
4 4 21 74 2
>
Rows 1, 2, and 4 each contain at least two non-missing values. Row 3 contains only one non-NA value, so it is excluded.
Let us try with N = 3.
> N=3
> resultDF = mydataframe[rowSums(is.na(mydataframe[ , 0:ncol(mydataframe)])) <= (ncol(mydataframe) - N), ]
> resultDF
x y z p
1 9 4 9 NA
4 4 21 74 2
>
With N = 3, only rows 1 and 4 qualify. Row 1 contains three non-missing values, while row 4 contains four.
Count Non-NA Values in Each R Data Frame Row
Before filtering, you can inspect the number of available values in every row. Applying !is.na() returns TRUE for each non-missing value, and rowSums() counts those values row by row.
non_na_count <- rowSums(!is.na(mydataframe))
non_na_count
1 2 3 4
3 2 1 4
The result shows that rows 1 through 4 contain three, two, one, and four non-NA values respectively. You can also save these counts in the data frame when they are useful for later analysis.
mydataframe$non_na_count <- rowSums(!is.na(mydataframe))
Filter Rows Using Only Selected R Data Frame Columns
Sometimes the minimum count should be calculated from only a few relevant columns rather than the complete data frame. Select those columns before applying is.na().
columns_to_check <- c("x", "y", "z")
N <- 2
resultDF <- mydataframe[
rowSums(!is.na(mydataframe[columns_to_check])) >= N,
]
This keeps rows that have at least two non-missing values across x, y, and z. Values in column p do not affect the filter.
Filter Rows with at Least N Non-NA Values Using dplyr
In dplyr, use if_any(), if_all(), or rowSums() depending on the condition. To keep rows with at least N non-missing values across all columns, calculate the count inside filter().
library(dplyr)
N <- 2
resultDF <- mydataframe |>
filter(rowSums(!is.na(pick(everything()))) >= N)
To check only selected columns, pass those column names to pick().
resultDF <- mydataframe |>
filter(rowSums(!is.na(pick(x, y, z))) >= 2)
Filter Rows with No NA Values or At Least One Non-NA Value
The same counting method handles common missing-value filters.
- To keep fully complete rows, require the number of non-
NAvalues to equal the number of columns. - To keep rows containing at least one usable value, require the count to be at least 1.
- To keep rows with an exact number of non-missing values, compare the count with
==.
# Keep rows with no NA values
complete_rows <- mydataframe[rowSums(!is.na(mydataframe)) == ncol(mydataframe), ]
# Keep rows with at least one non-NA value
partly_complete_rows <- mydataframe[rowSums(!is.na(mydataframe)) >= 1, ]
# Keep rows with exactly two non-NA values
exactly_two <- mydataframe[rowSums(!is.na(mydataframe)) == 2, ]
For complete rows, complete.cases(mydataframe) is a concise alternative:
complete_rows <- mydataframe[complete.cases(mydataframe), ]
Why NA Comparisons Should Use is.na() in R
Do not test missing values with expressions such as x == NA or x != NA. An unknown value cannot be compared as an ordinary number or string, so those expressions return NA rather than a useful TRUE or FALSE result.
Use is.na(x) to identify missing values and !is.na(x) to identify non-missing values.
is.na(x)
!is.na(x)
Common Errors When Filtering R Rows by Non-NA Count
- Using
NA == NAinstead ofis.na(). - Counting all columns when only a selected group should determine row completeness.
- Using
na.omit()when partially complete rows should remain in the result. - Setting
Ngreater than the number of checked columns, which produces an empty result. - Including a previously created count column in a later non-
NAcalculation and unintentionally changing the threshold logic.
FAQs About Filtering R Rows with Non-NA Values
How do I filter for non-NA values in R?
For one column, use df[!is.na(df$column), ]. With dplyr, use filter(df, !is.na(column)).
How do I keep rows with at least two non-NA values in R?
Use df[rowSums(!is.na(df)) >= 2, ]. The expression counts available values in each row and retains rows whose count is at least two.
How do I filter NA values across multiple selected columns?
Select the columns before counting, as in df[rowSums(!is.na(df[c("a", "b", "c")])) >= N, ].
What is the difference between complete.cases() and a non-NA threshold?
complete.cases() retains only rows with no missing values in the checked columns. A threshold condition such as rowSums(!is.na(df)) >= N can retain partially complete rows.
How do I count the number of non-NA observations in each row?
Use rowSums(!is.na(df)). It returns one count for each row in the data frame.
Editorial QA Checklist for R Non-NA Row Filters
- Verify that each example distinguishes between counting
NAvalues and counting non-NAvalues. - Confirm that the stated value of
Nmatches the rows shown in each result. - Check whether the filter should inspect all columns or only a named subset.
- Ensure that
is.na()is used instead of direct equality comparisons withNA. - Confirm that newly added R syntax and output blocks use the correct PrismJS classes.
Summary of Filtering R Data Frames by Non-NA Count
Use rowSums(!is.na(mydataframe)) >= N to keep rows with at least N non-missing values. Select specific columns before counting when only part of the data frame should determine eligibility. For rows that must contain no missing values, use complete.cases(). In this R Tutorial, we have learned to filter a Dataframe based on the number of non-NAs (or ofcourse NAs) in a row.
TutorialKart.com