What does the axis argument mean in NumPy and pandas?
Short answer
axis names the dimension the operation moves along and collapses. axis=0 runs down the rows to give a result per column, and axis=1 runs across the columns to give a result per row.
The short version
axis says which dimension an operation runs along and collapses. axis=0 works down the rows, so it combines all rows and returns one value per column. axis=1 works across the columns, so it combines all columns and returns one value per row. The phrase to hold onto is that the axis you name is the one that disappears.
Seeing both directions
import numpy as np
m = np.array([[1, 2, 3],
[4, 5, 6]])
print(m.sum(axis=0)) # [5 7 9] one total per column
print(m.sum(axis=1)) # [6 15] one total per row
axis=0 added 1+4, 2+5, 3+6, collapsing the two rows into a per-column result. axis=1 added each row's own values, collapsing the three columns into a per-row result.
Why "the axis disappears" helps
People often guess the wrong axis because they think of "along the rows" ambiguously. The reliable rule is: the numbered axis is removed from the shape. A 2 by 3 array summed with axis=0 loses the length-2 axis and becomes shape (3,). Summed with axis=1 it loses the length-3 axis and becomes shape (2,). Check the shape you want, and pick the axis that leaves it.
The same idea in pandas
Pandas uses the same convention, which is where a lot of confusion lives.
import pandas as pd
df = pd.DataFrame(m, columns=["a", "b", "c"])
df.sum(axis=0) # sum each column (down the rows)
df.sum(axis=1) # sum each row (across the columns)
axis=0 is the default for most pandas aggregations, giving one value per column, which matches "summarise each column". axis=1 is the one you reach for to combine several columns into a per-row result.
The drop gotcha in pandas
Confusingly, df.drop uses axis to mean which labels you are removing, so axis=1 there means "drop columns". This is consistent with "axis 1 is the column axis", but it reads differently from an aggregation, so read drop(axis=1) as "drop along the column axis", that is, drop columns.
A quick mnemonic
For a 2D array, think of axis=0 as the vertical arrow pointing down the rows (giving column results) and axis=1 as the horizontal arrow pointing across the columns (giving row results). When an aggregation gives you the wrong shape, you almost certainly want the other axis.
Higher dimensions
The same rule scales: for a 3D array, axis=2 collapses the last dimension. You can also pass a tuple to collapse several axes at once, for example arr.sum(axis=(0, 1)), which is occasionally useful when reducing over more than one dimension.