How to Delete a Column in Pandas (5 Methods With Examples)
How to Delete a Column in Pandas DataFrame
To delete a column in pandas, use df = df.drop(columns=["col_name"]). You can also use
del df["col_name"], df.pop("col_name"), or select only the columns you want to keep.
This guide covers all five methods with their real output, a comparison table, and the two
questions that come up most: why you get a KeyError, and whether inplace=True saves
memory.
Tested with: pandas 3.0.6, NumPy 2.5.3, Python 3.14.2, on 2026-10-05. Every output block below was produced by running the code above it.
Fixed on 2026-10-05. Earlier versions of this page reused one DataFrame across all sections. Section 1 dropped
scorein place, so thedel,pop()and column-selection examples raisedKeyError: 'score'when run in order. Each section now starts from a fresh copy of the sample data.
Every example below starts from the same sample DataFrame. Run this once:
import pandas as pd
def make_df():
return pd.DataFrame(
{
"name": ["Ada", "Bob", "Chloe"],
"age": [29, 35, 42],
"city": ["London", "Berlin", "New York"],
"score": [88, 91, 77],
}
)
df = make_df()
print(df) name age city score
0 Ada 29 London 88
1 Bob 35 Berlin 91
2 Chloe 42 New York 771. Using drop()
drop() is the most flexible option. It removes one or more columns and returns a new
DataFrame, leaving the original as it was.
df = make_df()
# Drop one column; df itself is unchanged
print(df.drop(columns=["city"]))
# Drop several columns and keep the result
df = df.drop(columns=["city", "score"])
print(df) name age score
0 Ada 29 88
1 Bob 35 91
2 Chloe 42 77
name age
0 Ada 29
1 Bob 35
2 Chloe 42columns=[...]says what you mean.df.drop(["city"], axis=1)does the same thing.inplace=Truemodifiesdfand returnsNone. Assigning the result back (df = df.drop(...)) is the usual style, andinplace=Truedoes not use less memory. See Doesinplace=Truesave memory? below.
Dropping a column that might not exist
drop() raises KeyError if a name is missing. When a column may or may not be there, for
example when cleaning files from different sources, pass errors="ignore":
df = make_df()
print(df.drop(columns=["score", "notes"], errors="ignore")) name age city
0 Ada 29 London
1 Bob 35 Berlin
2 Chloe 42 New York2. Using the del statement
Python’s del removes a column from the DataFrame in place.
df = make_df()
del df["score"]
print(df) name age city
0 Ada 29 London
1 Bob 35 Berlin
2 Chloe 42 New York- Pros: short and clear.
- Cons: one column at a time, and a missing name raises
KeyErrorwith no option to ignore it.
3. Using pop()
pop() works like the list method: it removes the column and returns it as a Series.
Use it when you want to keep the values, for example to split off a target column before
training a model.
df = make_df()
scores = df.pop("score")
print(df)
print(scores) name age city
0 Ada 29 London
1 Bob 35 Berlin
2 Chloe 42 New York
0 88
1 91
2 77
Name: score, dtype: int64The returned Series keeps the original index, so it lines up with the rows of df.
4. Selecting the columns to keep
Instead of deleting columns, build a DataFrame from the ones you want. This reads well when you keep fewer columns than you drop.
df = make_df()
subset = df[["name", "score"]]
print(subset) name score
0 Ada 88
1 Bob 91
2 Chloe 77In pandas 3, subset behaves as an independent DataFrame. Changing it never changes df,
so you do not need .copy() to protect the original.
5. Using loc or iloc
loc selects columns by label or with a boolean mask. iloc selects by position. Both are
useful when the columns to drop follow a rule rather than a fixed list.
df = make_df()
# Every column except "score"
print(df.loc[:, df.columns != "score"])
# Drop every column whose name contains "c" (here: "city" and "score")
print(df.loc[:, ~df.columns.str.contains("c")])
# Keep the first and last columns by position
print(df.iloc[:, [0, -1]]) name age city
0 Ada 29 London
1 Bob 35 Berlin
2 Chloe 42 New York
name age
0 Ada 29
1 Bob 35
2 Chloe 42
name score
0 Ada 88
1 Bob 91
2 Chloe 77Summary table
| Method | Changes df itself? | Returns | Missing column | Best use case |
|---|---|---|---|---|
df = df.drop(columns=[...]) | No (you reassign) | New DataFrame | KeyError, or skip with errors="ignore" | Most cases, several columns at once |
df.drop(columns=[...], inplace=True) | Yes | None | Same as above | Same result as reassigning |
del df["col"] | Yes | — | KeyError | One column; avoided the middle-column copy in our test |
df.pop("col") | Yes | Series | KeyError | Removing a column and keeping its values |
df[[...]] | No | New DataFrame | KeyError | Keeping a short list of columns |
df.loc[:, mask] / df.iloc[:, [...]] | No | New DataFrame | Not applicable (mask) | Dropping by rule or by position |
Does inplace=True save memory?
A common tip says to use inplace=True on large DataFrames to avoid copying data. In
pandas 3, which uses Copy-on-Write by default, we measured the peak new memory each
operation allocated on an 80 MB DataFrame (5 float64 columns × 2,000,000 rows). Which
column you remove turns out to matter more than inplace:
| Operation | Last column (c4) | Middle column (c2) |
|---|---|---|
df = df.drop(columns=[...]) | 0.01 MB | 64.01 MB |
df.drop(columns=[...], inplace=True) | 0.01 MB | 64.01 MB |
del df[...] | ≤ 0.01 MB | ≤ 0.01 MB |
s = df.pop(...) | 0.01 MB | 0.01 MB |
df[[...]] keeping the other four | 0.01 MB | 64.01 MB |
df.loc[:, df.columns != ...] | not measured | 64.01 MB |
control: df.copy() | 80.00 MB | — |
The numbers were the same whether the DataFrame was built from a dict of columns or from one 2-D array.
What this means:
inplace=Truesaves nothing. It allocated exactly what the reassigning form did in every case.- Removing the last column copies nothing with any method. The result shares memory with the original.
- Removing a column from the middle copies the remaining data with
drop()and with column selection: 64 MB here, the four columns that are kept.delandpop()did not copy in either case.
So in these measurements, del df["col"] or df.pop("col") was the cheaper way to
remove a middle column. We did not measure the first column. Otherwise, choose by what reads best and what you need
returned. When the result of drop() shares memory with the original, writing to it later
copies only what you change: one cell written into a drop() result allocated 16 MB, one
column’s worth, and the original was unchanged.
These measurements cover pandas 3.0.6 and float64 columns only. pandas 2.x without
Copy-on-Write behaves differently, and we did not measure it. Memory was measured with
Python’s tracemalloc, which NumPy reports its allocations to. The df.copy() control
confirms it catches an 80 MB copy.
Conclusion
- Use
df = df.drop(columns=[...])by default. Adderrors="ignore"when a column might not exist. - Use
pop()when you need the removed values. - Use
delfor one known column in a quick script. In our measured float64 frames, deleting a middle column withdelalso avoided the 64 MB copy thatdrop()made. - Use column selection or
loc/ilocwhen it is easier to say what to keep, or when the columns to drop follow a pattern.
If you worked these cleaning steps out in a Jupyter notebook and now want them as a .py
script for a pipeline, the Jupyter to Python converter
turns an .ipynb into a script in the browser. For converting notebooks from the command
line, including to HTML and PDF, see the nbconvert tutorial.