HOWTO · Pandas
How to Copy Pandas DataFrame
Learn how DataFrame.copy() creates a DataFrame copy, how deep=True and deep=False differ, and why assignment does not make an independent copy.
On this page
To make a pandas DataFrame copy, call DataFrame.copy(). Its default, deep=True, gives you a separate DataFrame so that changing a cell in the result leaves the original cell unchanged. Use this when you need to edit data independently.
DataFrame.copy() Syntax and Copy Depth
The method accepts the deep argument: df.copy(deep=True). The default is True, so df.copy() is equivalent. With deep=True, pandas copies the DataFrame’s data and index. This is a deep copy of pandas’ data structures, but it does not recursively copy Python objects stored in cells with object dtype. If a cell contains a mutable list, for example, the copied DataFrame can still contain a reference to that same list. Copy the contained objects separately if your task requires independent nested objects.
With deep=False, pandas initially shares the underlying data and index with the source rather than copying them. What a later assignment through either DataFrame does depends on the pandas version and whether Copy-on-Write is enabled. Do not rely on a shallow copy either to propagate edits to the source or to isolate them across every setup. If independence matters, use the default deep copy. If shared data is intentional, check the behavior documented for the pandas version and Copy-on-Write mode used by your application.
Create an Independent DataFrame Copy
Run this example:
import pandas as pd
original = pd.DataFrame({"score": [10]})
independent = original.copy()
independent.loc[0, "score"] = 99
print(f"original={original.loc[0, 'score']}, copy={independent.loc[0, 'score']}")
original=10, copy=99
The assignment changes the copied DataFrame’s cell, while the value in original remains 10. The example uses the default deep=True; writing original.copy(deep=True) makes that choice explicit. Use .loc[row, column] to identify the cell you want to update, and keep the original variable available when you need to compare or reuse its data.
Understand deep=False and Shared Data
A shallow copy can be useful when you want a new DataFrame object without immediately duplicating its data. It is not a universal promise about what a later mutation will do: pandas’ Copy-on-Write behavior and version affect whether a write is isolated or visible through another object. Treat deep=False as a choice with version-dependent mutation semantics, not as a reliable way to edit both DataFrames together. For predictable independent edits, choose deep=True; for behavior tied to a particular application, verify its pandas version and Copy-on-Write setting.
The deep argument also does not make nested objects independent. For example, if object-dtype cells contain lists, a DataFrame copy duplicates the pandas containers but does not recursively clone each list. Mutating a list in a cell can therefore affect an object reachable from both DataFrames. Handle nested mutable values separately when that distinction matters.
Assigning a DataFrame or Column to a Variable
An assignment such as other = original binds another variable to the same DataFrame object. It does not call DataFrame.copy() or create independent data. A change made through either name acts on that same object.
Likewise, scores = original["score"] selects a column as a pandas Series; it does not explicitly request an independent copy. Do not use variable assignment or column selection as a substitute for a copy when isolation is required. Use other = original.copy() for a DataFrame or scores = original["score"].copy() for a separate Series. This makes your intent clear and avoids relying on incidental view or mutation behavior. Choose the object you need first—a DataFrame for tabular operations or a Series for one column—then call .copy() when you need a separately editable result.