Removing Missing Values in Pandas – When and How to Use dropna() 2026
Removing missing values using dropna() is one of the simplest and fastest ways to clean your dataset. While not always the best strategy, it is often appropriate when missing values are few or when complete cases are required for analysis.
TL;DR — dropna() Parameters
axis=0→ Drop rows (default)axis=1→ Drop columnshow="any"→ Drop if any value is missing (default)how="all"→ Drop only if all values are missingthresh=n→ Keep rows with at least n non-missing values
1. Basic Usage of dropna()
import pandas as pd
# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
"order_date": pd.date_range("2026-01-01", periods=n, freq="3D"),
"customer_id": rng.integers(101, 121, n),
"customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
"product_id": rng.integers(1, 9, n),
"region": rng.choice(["North", "South", "East", "West"], n),
"category": rng.choice(["Electronics", "Computers", "Books", "Home"], n),
"payment_method": rng.choice(["card", "cash", "wallet"], n),
"segment": rng.choice(["consumer", "business"], n),
"quantity": rng.integers(1, 6, n),
"amount": rng.uniform(50, 2500, n).round(2),
"discount": rng.choice([0.0, 0.05, 0.1, 0.2], n),
}).assign(
price=lambda d: (d["amount"] / d["quantity"]).round(2),
profit=lambda d: (d["amount"] * rng.uniform(0.05, 0.3, n)).round(2),
).assign(
ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)
df = pd.read_csv("sales_data.csv", parse_dates=["order_date"])
print(f"Original shape: {df.shape}")
# Drop rows with any missing values
df_clean = df.dropna()
print(f"After dropna(): {df_clean.shape}")
print(f"Rows removed: {len(df) - len(df_clean)}")
2. Common dropna() Strategies
# 1. Drop rows only if ALL values are missing
df_clean = df.dropna(how="all")
# 2. Drop columns that have too many missing values
df_clean = df.dropna(thresh=len(df)*0.7, axis=1) # Keep columns with at least 70% non-missing
# 3. Drop rows based on specific columns only
df_clean = df.dropna(subset=["amount", "region", "customer_id"])
# 4. Drop rows with missing values in critical columns
critical_cols = ["order_date", "amount", "customer_id"]
df_clean = df.dropna(subset=critical_cols)
3. Real-World Example
# Before cleaning
print("Missing values before:")
print(df.isna().sum()[df.isna().sum() > 0])
# Clean strategy: Keep only complete records for key business columns
df_clean = df.dropna(subset=["order_date", "amount", "region", "customer_id"])
print(f"\nRows before: {len(df)}")
print(f"Rows after: {len(df_clean)}")
print(f"Percentage kept: {(len(df_clean)/len(df)*100):.1f}%")
4. Best Practices in 2026
- Always check how many rows/columns will be removed before dropping
- Use
subsetto drop based only on important business columns - Use
threshto keep columns that are mostly complete - Consider imputation instead of dropping when missingness is high (>10-20%)
- Document your dropping strategy and the percentage of data lost
- Never drop rows blindly without understanding the business impact
When dropna Is the Right Choice
dropna() removes rows, or columns with axis=1, that contain missing values. It is a good choice when gaps are few, random, and in rows you can afford to lose, and a poor one when it would remove a large or biased part of the data.
Its options give precise control: subset= limits the check to important columns, how="all" drops only fully empty rows, and thresh= keeps rows with at least a given number of real values.
Worked Example: Precise Dropping
Each option is applied to the same table so the row counts can be compared.
import pandas as pd
import numpy as np
df = pd.DataFrame({
"id": [1, 2, 3, 4, 5],
"price": [10.0, np.nan, 12.0, np.nan, 9.0],
"note": [None, "ok", None, None, "late"],
})
print(len(df.dropna()))
print(len(df.dropna(subset=["price"])))
print(len(df.dropna(thresh=2)))
print(df.dropna(axis=1).columns.tolist())
print(f"kept {len(df.dropna(subset=['price'])) / len(df):.0%} of rows")
A plain dropna() keeps only one row because the note column is often empty. Limiting the check to price keeps three rows, and printing the kept share makes the cost of dropping visible.
Common Mistakes
- Dropping on all columns when only a few matter.
- Losing a large share of rows without noticing.
- Dropping columns with axis=1 by accident.
- Dropping data that is missing for a systematic reason.
Quick Summary
- dropna() removes incomplete rows or columns.
- subset= focuses on important columns.
- how= and thresh= control strictness.
- Always report how many rows were dropped.
Conclusion
Removing missing values with dropna() is fast and simple, but it should be used thoughtfully. In 2026, the best practice is to first understand the pattern of missingness, then decide whether to drop rows, drop columns, or use imputation. Use subset and thresh parameters to make your dropping strategy more intelligent and business-aligned.
Next steps:
- Analyze the missing values in your current dataset and decide which strategy (drop rows, drop columns, or impute) is most appropriate