Written and maintained by CASRAI Editorial Board
Last updated
To omit rows with NA in R, run na.omit(df) to drop every row that has a missing value in any column, tidyr::drop_na(df, x) to drop rows only where selected columns are missing, or df[complete.cases(df), ] to subset by a logical index. All three remove rows; they differ in which columns they inspect and in what they tell you about the rows they removed. This guide runs all three on one small data frame and shows how to report how many rows were lost, which is the step most tutorials skip.
What omitting NA rows is used for in research
Many R functions cannot use a row that has a missing value, so analysts remove incomplete rows before computing statistics or fitting a model. This is listwise (complete-case) deletion: a row is kept only if it is complete across the columns considered. Deleting rows changes the sample, so the number removed belongs in the methods or data-cleaning record. CASRAI’s listwise vs pairwise deletion comparison covers the trade-off between the two deletion strategies, and data cleaning steps places row removal among the other cleaning decisions.
Install or access
na.omit() and complete.cases() are in the stats package that ships with R, so nothing needs installing (R manual, stats package, checked 2026-10-29). drop_na() comes from tidyr. The tidyr site gives two ways to install it, either the whole tidyverse or tidyr alone (checked 2026-10-29):
install.packages("tidyverse")
# or just tidyr:
install.packages("tidyr")
library(tidyr)
Step-by-step: remove rows with NA in R
The steps below use the data frame from the R manual’s example for na.omit, with one missing value in column y.
DF <- data.frame(x = c(1, 2, 3), y = c(0, 10, NA))
- Drop every row with any NA, with
na.omit(). Runna.omit(DF). The third row, which holds the NA iny, is removed and rows 1 and 2 remain. The manual defines the argument as “an R object, typically a data frame”. - Drop rows with NA in selected columns only, with
drop_na(). Its usage isdrop_na(data, ...), where the dots are the columns to inspect and, in the tidyr reference’s words, “If empty, all columns are used.” On the tidyr exampledf <- tibble(x = c(1, 2, NA), y = c("a", NA, "b")):df |> drop_na()keeps 1 row, (1, a).df |> drop_na(x)keeps 2 rows, (1, a) and (2, NA), because onlyxis checked.
- Build a logical index with
complete.cases().ok <- complete.cases(DF)returns a logical vector that is TRUE for each row with no missing value. Keep those rows withDF[ok, ]. The manual’s own example does the same withx <- x[ok,].
Remove rows with NA in R: choosing the method
When you want every column complete
Use na.omit(DF) or drop_na(DF). Both inspect all columns, so a missing value in any column removes the row.
When only some columns matter
Use drop_na(DF, x) and name the columns. The tidyr example above shows that a row with NA in an unlisted column survives. If you use na.omit() on a wider data frame than your analysis needs, you can lose rows because of columns you never use, so subset to the relevant columns first.
Output and how to read it
The result is the same data frame minus the incomplete rows. The useful extra from na.omit() is recorded on the result: “If na.omit removes cases, the row numbers of the cases form the “na.action” attribute of the result, of class “omit”” (R manual). To read it, use attr(na.omit(DF), "na.action") to get the row numbers that were dropped.
To report how many rows were lost without keeping the attribute, use the pattern from the complete.cases manual example, sum(!ok), which counts the rows that are not complete. A one-line record such as “3 rows, 1 removed for missing y” is enough to make the cleaning step reproducible. Whether deleting those rows is defensible depends on why the values are missing, which no function can check for you.
The same silent dropping happens inside modelling and summary functions, where missing rows are omitted by default. CASRAI’s guides on logistic regression in R and standard deviation in R show where that default appears and how to check the sample size that was actually used.
Troubleshooting
- Nothing changed.
na.omit()does not affect objects with no NAs; the manual’s example asserts thatna.omit(1:3)equals1:3. Check that your missing values are real NA values in the column you expect. - An error saying missing values were found. That comes from
na.fail(), the sibling function on the same manual page, which stops with “missing values in …” instead of removing rows. The manual’s example wraps it intry(na.fail(DF)). The manual’s example also callsoptions("na.action")to show the current missing-value setting. - Too many rows disappeared. You probably inspected all columns. Switch to
drop_na()with the columns your analysis uses, or replace missing values rather than delete them, as in replacing NA with 0 in R where that is appropriate for your data.
Alternatives compared
| Function | Package | Columns inspected | What it returns |
|---|---|---|---|
na.omit(object) |
stats | All columns | The object without incomplete rows, with the removed row numbers in the “na.action” attribute |
complete.cases(...) |
stats | All columns of every argument supplied | A logical vector, one value per row, TRUE where the row has no missing values |
drop_na(data, ...) |
tidyr | The columns you name; all columns if none are named | The data frame without rows that have NA in the inspected columns |
FAQ
How do I omit rows with NA in R?
Use na.omit(df) for all columns, or df |> drop_na() from tidyr. Both return the data frame without rows that contain a missing value.
How do I remove rows with NA in R for one column only?
Use drop_na(df, x) with the column name. In the tidyr example, this keeps the row (2, NA) because y is not inspected.
How can I tell how many rows were removed?
Count the incomplete rows with sum(!complete.cases(df)), or read the “na.action” attribute of the na.omit() result.
Does na.omit() change my original data frame?
It returns a result and leaves df as it was unless you overwrite it. Assign the result to a new name, such as df_complete <- na.omit(df), so you keep both versions.
Sources
- R Core Team, R manual, stats package: na.fail / na.omit, checked 2026-10-29.
- R Core Team, R manual, stats package: complete.cases, checked 2026-10-29.
- tidyverse: tidyr drop_na() reference (tidyr 1.3.2), checked 2026-10-29.
- tidyverse: tidyr home page and installation, checked 2026-10-29.







