Understanding the axis Argument in Pandas – axis=0 vs axis=1 Explained 2026
The axis parameter is one of the most important and frequently misunderstood concepts in Pandas. Mastering axis=0 (rows) versus axis=1 (columns) is essential for effective data manipulation.
TL;DR — axis Explained Simply
axis=0→ Operate down the rows (column-wise operation)axis=1→ Operate across the columns (row-wise operation)- Think: "0 = vertical (like the y-axis in math), 1 = horizontal"
1. Basic Examples of axis
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")
# numeric_only=True: pandas 3 no longer skips text columns silently
# axis=0 → along rows (default for most operations)
column_sums = df.sum(axis=0, numeric_only=True) # Sum of each column
column_means = df.mean(axis=0, numeric_only=True)
# axis=1 → along columns
row_sums = df.sum(axis=1, numeric_only=True) # Sum of each row
row_means = df.mean(axis=1, numeric_only=True)
2. Common Operations with axis
# Drop rows with missing values
df_clean = df.dropna(axis=0) # Drop rows (default)
# Drop columns with missing values
df_clean = df.dropna(axis=1) # Drop columns
# Mean of each column
col_means = df.mean(axis=0, numeric_only=True)
# Mean of each row
row_means = df.mean(axis=1, numeric_only=True)
# Fill missing values column-wise
df.fillna(df.mean(axis=0, numeric_only=True), axis=0) # Fill with column mean
3. Real-World Example with groupby + axis
# Sum sales by region (group along rows)
sales_by_region = df.groupby("region")["amount"].sum()
# Calculate percentage of total for each row
df["percentage"] = df["amount"] / df["amount"].sum(axis=0) * 100
# Normalize each row (row-wise operation)
df_normalized = df[["amount", "quantity"]].div(
df[["amount", "quantity"]].sum(axis=1),
axis=0
)
4. Best Practices in 2026
- Use
axis=0when you want to operate per column (most common) - Use
axis=1when you want to operate per row - Always be explicit with
axisinstead of relying on default behavior - When in doubt, remember:
axis=0affects rows (vertical),axis=1affects columns (horizontal) - Use meaningful variable names to avoid confusion when using
axis=1
What the Axis Argument Means
axis tells pandas the direction in which an operation runs. axis=0, or axis="index", works down the rows and produces one result per column. axis=1, or axis="columns", works across the columns and produces one result per row.
A helpful rule is that the axis you name is the one that collapses. df.sum(axis=0) collapses the rows, while df.drop("col", axis=1) removes something along the columns. In pandas 3, summaries on mixed tables need numeric_only=True to skip text columns.
Worked Example: Totals per Column and per Row
Student scores are summed and averaged in both directions to show the difference.
import pandas as pd
df = pd.DataFrame({
"name": ["Ana", "Ben", "Cara"],
"math": [80, 90, 70],
"science": [85, 75, 95],
})
print(df.sum(axis=0, numeric_only=True))
print(df.mean(axis="columns", numeric_only=True))
df["total"] = df[["math", "science"]].sum(axis=1)
print(df.drop("name", axis=1))
axis=0 returns one total per subject, while axis=1 gives each student an average or total. Selecting the numeric columns explicitly before a row-wise sum keeps the result easy to reason about.
Common Mistakes
- Swapping axis=0 and axis=1 and getting the wrong shape.
- Summing mixed text and number columns without numeric_only=True.
- Forgetting axis=1 when dropping a column with drop().
- Using row-wise apply where a vectorised axis=1 method exists.
Quick Summary
- axis=0 works down rows: one result per column.
- axis=1 works across columns: one result per row.
- Named forms "index" and "columns" improve readability.
- Use numeric_only=True for mixed DataFrames.
Conclusion
The axis argument is fundamental to understanding how Pandas operations work. In 2026, always be explicit with axis=0 (operate down columns) and axis=1 (operate across rows). Mastering this concept will eliminate many common bugs and make your data manipulation code much more predictable and professional.
Next steps:
- Review your current Pandas code and make sure you are using
axisexplicitly and correctly in allsum(),mean(),dropna(), andfillna()operations