Pandas Add, Update, Rename, and Drop Columns
python pandas add update rename and drop columns: Practical syntax for adding, updating, renaming, and dropping columns in pandas DataFrames, with the edge cases that...
Adding, updating, renaming, and dropping columns are the four column operations you will use constantly when cleaning or transforming data in pandas. The core syntax is compact, but a few details—index alignment, inplace behavior, and copy semantics—can produce subtle bugs. This article covers the practical syntax for python pandas add update rename and drop columns and the edge cases that matter in real code.
Adding Columns to a DataFrame
The most direct way to add a column is assignment:
import pandas as pd df = pd.DataFrame({"name": ["Ada", "Grace", "Alan"]}) df["score"] = [95, 88, 91]
This appends the score column at the end of the DataFrame. The assigned value can be a list, a Series, a scalar, or a NumPy array. A scalar broadcasts to every row:
df["active"] = True
When the assigned value is a Series, pandas aligns it by index label rather than by position. If the Series has a different index order or contains labels that do not exist in the DataFrame, the result will contain NaN for the missing positions. This alignment behavior is useful when combining data from separate sources, but it can silently produce missing values if you assume positional matching.
insert places a column at a specific position instead of appending it:
df.insert(1, "role", ["Mathematician", "Admiral", "Scientist"])
The first argument is the integer position, the second is the column name, and the third is the values. insert modifies the DataFrame in place and raises a ValueError if the column name already exists, unless allow_duplicates=True is passed. It also raises a ValueError when the position is negative or beyond the current number of columns.
assign returns a new DataFrame with the added column, leaving the original untouched:
df2 = df.assign(score=lambda d: d["score"] * 1.1)
assign fits naturally into method chains. The lambda receives the DataFrame and can reference existing columns, which makes it convenient for deriving one column from another without a separate assignment statement.
Updating Existing Columns
Reassigning a column replaces its entire contents:
df["score"] = df["score"] + 5
This is a vectorized operation; pandas applies the arithmetic to every element without an explicit Python loop. For conditional updates, use loc with a boolean mask:
df.loc[df["score"] < 90, "score"] = 90
This updates only the rows where the condition is true. The mask and the assignment target share the same DataFrame, so index alignment is not a concern here. Avoid the chained form df["score"][df["score"] < 90] = 90, which can operate on a copy and trigger a SettingWithCopyWarning.
replace performs value-level substitution within a column:
df["status"] = df["status"].replace({"pending": "queued", "done": "complete"})
apply runs a Python function across each element or row. It is more flexible than vectorized operations but slower because it invokes the function once per element:
df["slug"] = df["name"].apply(lambda n: n.lower().replace(" ", "-"))
Use apply when the transformation cannot be expressed with vectorized pandas methods. For simple arithmetic, string methods via str, or datetime methods via dt, prefer the vectorized form; it is faster and usually more readable.
Renaming Columns
rename maps old column names to new ones:
df = df.rename(columns={"name": "full_name", "score": "points"})
rename returns a new DataFrame by default. Passing inplace=True modifies the original:
df.rename(columns={"name": "full_name"}, inplace=True)
inplace=True is a common source of confusion because its behavior is not uniform across pandas methods. For rename, drop, and fillna, it mutates the object directly. Other methods accept the parameter but may ignore it or emit a deprecation warning. The explicit assignment form is the most predictable across pandas versions, so prefer it unless you specifically want to mutate the original object.
A less common approach is to assign the columns attribute directly:
df.columns = ["full_name", "role", "points"]
This replaces the entire column index. It is fast and works well when you know the full ordered list of names, but it requires every column to be present in the correct order. It also discards any existing column metadata, which is rarely a concern for ordinary DataFrames.
Dropping Columns
drop removes columns by name:
df = df.drop(columns=["role", "notes"])
The columns parameter makes the intent explicit. The older signature df.drop(["role"], axis=1) still works but is less readable and easier to confuse with row dropping.
By default, drop raises a KeyError if a requested column does not exist. Pass errors="ignore" to skip missing names silently:
df = df.drop(columns=["missing_col"], errors="ignore")
drop also accepts inplace=True, which mutates the original DataFrame instead of returning a copy.
When you want to keep a small set of columns rather than remove a large set, selecting the columns directly is often clearer:
df = df[["name", "score"]]
This is equivalent to dropping every other column and avoids listing all the columns you want to remove. It also makes the resulting schema explicit at the point of selection.
Performance and Memory Behavior
Column operations in pandas differ significantly in cost.
Direct assignment and vectorized arithmetic operate on the underlying NumPy arrays without Python-level loops. They are the fastest way to add or update a column.
apply with a Python function pays a per-element function-call overhead. On large DataFrames, this can be orders of magnitude slower than a vectorized expression. Before reaching for apply, check whether the operation exists as a vectorized method: string methods via str, datetime methods via dt, and arithmetic operators cover most common cases.
inplace=True does not guarantee lower memory usage. Pandas may still allocate intermediate arrays during the operation. The practical benefit of inplace is mostly about code style and avoiding rebinding the variable name, not about reducing memory footprint.
When you drop columns, pandas returns a new DataFrame that may share underlying data blocks with the original for the remaining columns. The memory for the dropped columns is released only when the original DataFrame is garbage-collected. In a long-running process, keeping a reference to the original prevents that memory from being reclaimed.
Common Pitfalls
Chained assignment. df["col"][df["col"] > 10] = 0 operates on a copy in some pandas versions and raises a SettingWithCopyWarning. Use df.loc[df["col"] > 10, "col"] = 0 instead.
Index alignment in assignment. When you assign a Series to a column, pandas aligns by index. If the Series has a different index, the result may contain NaN even though the values look correct. Verify the index of the source Series before assignment.
inplace inconsistency. Not every method that accepts inplace=True behaves identically. Some methods ignore it or emit deprecation warnings. The explicit assignment form is the most predictable across pandas versions.
Duplicate column names. df["col"] returns a DataFrame when the name appears more than once, not a Series. This breaks downstream code that expects a Series. rename and drop operate on all columns with the matching name, which can produce surprising results.
insert with an out-of-range position. insert raises a ValueError if the position is negative or exceeds the number of columns. It does not clamp the position to the valid range.