How do I check whether every column in a row meets a condition?
Short answer
Apply the condition to the whole frame and reduce with all(axis=1) for a per-row answer, or all(axis=0) for a per-column one. The axis argument decides which direction is collapsed.
The short version
Build a boolean frame with your condition, then reduce it with .all(axis=1) to get one answer per row, or .all(axis=0) for one per column. The axis you name is the one that disappears. any works the same way for "at least one".
Per row and per column
import pandas as pd
df = pd.DataFrame({"a": [1, 5], "b": [2, 6]})
positive = df > 3
positive.all(axis=1).tolist() # [False, True] , one answer per row
positive.all(axis=0).tolist() # [False, False] , one answer per column
Row 1 has both values above 3, so it is True. Row 0 does not. With axis=0, neither column is entirely above 3.
Remembering the axis
The rule that works everywhere in pandas and NumPy: the axis you name is collapsed. axis=1 collapses the columns, leaving one value per row. axis=0 collapses the rows, leaving one value per column.
If you get a result with the wrong length, you have almost certainly used the other axis.
Filtering on a whole-row condition
The natural use is keeping rows where every column passes a check.
complete = df[df.notna().all(axis=1)] # rows with no missing values anywhere
This is exactly what dropna() does, but writing it explicitly lets you vary the rule, for example requiring only certain columns to be present.
key_columns = ["city", "amount"]
df[df[key_columns].notna().all(axis=1)]
Checking a subset of columns
Select the columns first, then reduce, which is clearer than trying to express the restriction inside the condition.
numeric = df.select_dtypes("number")
df[(numeric > 0).all(axis=1)] # rows where every numeric column is positive
any for the opposite question
df[(df < 0).any(axis=1)] # rows with at least one negative value anywhere
This is a fast way to find problem rows across a wide frame without naming each column.
Reducing to a single answer
Chaining two reductions collapses the whole frame to one boolean, which is how you write a validation check.
if (df < 0).any().any():
raise ValueError("negative values found somewhere in the data")
The first any() gives one answer per column, the second collapses those to one overall. Forgetting the second call leaves you with a Series where you expected a boolean, and using it in an if raises the ambiguous-truth-value error.
Counting instead of testing
Summing the boolean frame tells you how many cells, rows or columns are affected, which is often more useful than a bare True or False.
(df < 0).sum() # count of negatives per column
(df < 0).any(axis=1).sum() # how many rows contain any negative
These two numbers together tell you both the scale of a data problem and whether it is concentrated in a few rows or spread everywhere, which usually points straight at the cause.