Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

Remove a Column in R: NULL, select(), subset() and Negative Indexing

Remove a column in R with NULL, [ , -n], subset() or dplyr select(!): worked examples, a method comparison table and the silent-failure traps.

Written and maintained by CASRAI Editorial Board

Last updated

Short answer: to remove a column from a data frame in R, assign NULL to it (df$col <- NULL, which changes df in place), or build a copy without it with a negative index (df[, -2], df[, setdiff(names(df), "col")]), subset(df, select = -col), or dplyr’s select(df, !col). This guide is for researchers cleaning an analysis data set who need to know which method to use, and which ones fail quietly when a column name is wrong.

What it is used for in research

Dropping columns is a routine step when preparing a data set for analysis: removing direct identifiers before sharing data, discarding scratch or helper variables, or trimming a wide export to the variables named in a pre-specified analysis plan. Do the removal in a script that reads the raw file and writes a new object or file, never by editing the raw data. That keeps the step reproducible and reviewable. See transformation in R for the wider workflow and removing rows in R for the row-wise counterpart.

Install or access

The NULL assignment, negative indexing and subset() are part of base R, which you install from CRAN (cran.r-project.org); nothing else is needed. The select() function belongs to the dplyr package (dplyr.tidyverse.org):

install.packages("dplyr")
library(dplyr)

Step-by-step: remove one or more columns

The examples use the built-in iris data set, whose columns are Sepal.Length, Sepal.Width, Petal.Length, Petal.Width and Species. Work on a copy so you can compare the result.

1. Assign NULL (removes in place)

df <- iris
df$Species <- NULL
df[["Petal.Width"]] <- NULL
names(df)

The base R manual for data-frame extraction states that assigning NULL “deletes the column if a single column is selected”, and its own example is sw$new4 <- NULL # delete the column (R documentation, ?Extract.data.frame, read 2026-11-07). This changes the object itself rather than returning a new one.

2. Negative indexing (returns a copy)

df <- iris
df[, -5]                                               # drop the fifth column
df[, -c(1, 3)]                                         # drop columns 1 and 3
df[, !(names(df) %in% c("Sepal.Length", "Species"))]   # drop by name
df[, setdiff(names(df), "Species")]                    # same idea

The R documentation for [ says negative integers in i and j indicate “elements/slices to leave out of the selection” (?Extract, read 2026-11-07). To drop by name, build the set of names to keep, as above; a character vector cannot be negated directly, and positive and negative indices cannot be mixed in one call.

3. subset() with select

subset(iris, select = -Species)
subset(iris, select = -c(Sepal.Length, Petal.Length))

The subset() help page describes select as an expression indicating the columns to select and notes that columns can be dropped (see its examples) (?subset, read 2026-11-07). See subset in R for rows and columns together.

4. dplyr select() with !

library(dplyr)
iris |> select(!Species)
iris |> select(!c(Sepal.Length, Petal.Length))
iris |> select(!ends_with("Width"))

The dplyr reference states that “The ! operator negates a selection” and gives these patterns, including select(!c(Sepal.Length, Petal.Length)) and select(!ends_with("Width")) (dplyr.tidyverse.org/reference/select.html, read 2026-11-07). More on this verb is in select in R.

Choosing a method: what changes and what fails

Method Changes the object in place? Selects by Column name that does not exist
df$col <- NULL Yes Name No error; nothing is removed
df[, -n] No, returns a copy Position Not applicable (positions, not names)
df[, setdiff(names(df), "col")] No Name No error; nothing is removed
select(df, !all_of("col")) No Name Error
select(df, !any_of("col")) No Name No error; nothing is removed

The dplyr reference defines the difference between the last two rows: all_of() throws an out-of-bounds error if any name is missing, while any_of() is “the same as all_of(), except that no error is thrown for names that don’t exist”. Use all_of() when a missing column means something went wrong upstream, and any_of() when you are tidying files that may or may not contain a column. The base R rows describe standard behaviour that you can confirm in a few lines on a throwaway data frame.

Output and how to read it

After any removal, check the result rather than assuming it:

names(df)    # which columns remain
ncol(df)     # how many (iris has 5 before removal)
str(df)      # types of what is left

Comparing ncol() before and after confirms that the number of columns dropped is the number you intended. This catches the silent no-op cases in the table above.

Troubleshooting

The result is a vector, not a data frame

With df[, -1], if only one column remains, base R returns a vector, because the drop argument of [ defaults to dropping to the lowest dimension when one column is left. Use df[, -1, drop = FALSE] to keep a data frame.

Every column disappeared, or none did

The pattern df[, -which(names(df) == "col")] looks safe but is not: when the name does not match, which() returns integer(0), and negating an empty index selects no columns at all. Prefer setdiff(names(df), "col") or !(names(df) %in% "col").

“undefined columns selected” or “object not found”

These usually mean a misspelled name. Check the exact spelling and case with names(df), and use all_of() in dplyr if you want a misspelling to stop the script.

Removing columns by pattern

In dplyr, put selection helpers inside !, such as !starts_with() or !ends_with(), as in the examples above. In base R, filter the names first: df[, !grepl("Width", names(df))].

Free alternatives

Tool Drop a column Documentation
Base R (CRAN) df$col <- NULL, df[, -n], subset(df, select = -col) R manual pages ?Extract.data.frame, ?subset
dplyr (CRAN) select(df, !col) dplyr.tidyverse.org/reference/select.html

Both are free and open source. For the same task in Python, see how to drop columns in pandas.

FAQ

How do I remove a column in R by name?

Use df$col <- NULL to remove it in place, or select(df, !col) in dplyr to get a copy without it.

How do I remove multiple columns in R?

Use a vector of positions or names: df[, -c(1, 3)], subset(df, select = -c(a, b)), or select(df, !c(a, b)).

How do I remove a column that might not exist?

Use select(df, !any_of("col")), which does not throw an error for names that do not exist, or df$col <- NULL, which also does nothing when the column is absent.

Does removing a column change the original file?

No. These operations change the object in your R session. The file on disk changes only if you write the object back with a function such as write.csv(); write to a new file name and keep the raw data untouched. Related: how to rename columns in R.

Sources

  • R Core Team, Extract.data.frame and Extract manual pages, stat.ethz.ch/R-manual/R-devel/library/base/html/ (read 2026-11-07).
  • R Core Team, subset manual page, stat.ethz.ch/R-manual/R-devel/library/base/html/subset.html (read 2026-11-07).
  • dplyr documentation, Keep or drop columns using their names and types, dplyr.tidyverse.org/reference/select.html (read 2026-11-07).

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Remove a Column in R: NULL, select(), subset() and Negative Indexing

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →