apply() with axis=0, the default, calls func once per column, passing each column as a Series; axis=1 instead calls func once per row, passing each row as a Series, which is the more common use for row-wise custom logic that can't be expressed with simple vectorized operations. Because apply() invokes a Python function once per row or column, it runs at Python speed rather than pandas' fast, vectorized C-level operations, which makes it noticeably slower than an equivalent vectorized expression whenever one is actually available.
1Understanding df.apply()
apply() with axis=0, the default, calls func once per column, passing each column as a Series; axis=1 instead calls func once per row, passing each row as a Series, which is the more common use for row-wise custom logic that can't be expressed with simple vectorized operations. Because apply() invokes a Python function once per row or column, it runs at Python speed rather than pandas' fast, vectorized C-level operations, which makes it noticeably slower than an equivalent vectorized expression whenever one is actually available.
Before reaching for apply(), check whether the same logic can be expressed with a vectorized pandas/NumPy operation instead — apply() calls a Python function once per row, or column, which is dramatically slower than an equivalent built-in vectorized operation for anything beyond small datasets.
import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3], "b": [10, 20, 30]})
print(df.apply(lambda row: row["a"] + row["b"], axis=1))2Practical Example
Here is a real-world application of df.apply() showing how it is used in production Pandas code.
import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3]})
print(df["a"].apply(lambda x: x ** 2))3Best Practices
Follow these guidelines when working with df.apply():
1. Prefer a vectorized operation, built-in methods, arithmetic, np.where(), etc., over apply() whenever one can express the same logic, for significantly better performance
2. Reserve apply() for genuinely custom, row-wise logic that can't be cleanly vectorized
3. Pass axis=1 explicitly for row-wise operations, since the default axis=0 applies the function per column instead, which is a common source of confusion
Tip: Before reaching for apply(), check whether the same logic can be expressed with a vectorized pandas/NumPy operation instead — apply() calls a Python function once per row, or column, which is dramatically slower than an equivalent built-in vectorized operation for anything beyond small datasets.
import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3], "b": [10, 20, 30]})
print(df.apply(lambda row: row["a"] + row["b"], axis=1))