AttributeError: ‘NumPy NdArray’ Object Has No Attribute ‘Median’ | Fix Median Calls Fast

Use numpy.median(array, axis=…) or pandas Series.median(); ndarray has no .median(), so arr.median() triggers this AttributeError.

Seeing this crash mid-analysis feels annoying. The good news: the fix is straightforward once you know where median actually lives in the API. NumPy puts median in the module namespace, not on ndarray objects. That’s why np.median(arr) works and arr.median() fails with AttributeError: ‘NumPy NdArray’ object has no attribute ‘median’. The docs spell out the call shape and options, including axis and keepdims.

Why You See This Error

NumPy arrays expose many methods, yet not every statistic sits there. Median is implemented as a function in the NumPy module, together with related tools like nanmedian and masked-array helpers. So a direct method call on an ndarray raises the attribute message. A classic traceback from this mix-up shows up across Q&A threads and teaching notes, which point users back to np.median.

Quick check: run np.median(your_array). If you need a per-column or per-row result, add axis. The function supports axis=None for a single value, or an integer axis for grouped results, plus keepdims=True to retain shape for downstream math. The reference describes these parameters and edge cases.

import numpy as np

arr = np.array([[1, 9, 3],
                [7, 5, 2]])

np.median(arr)          # 4.0 (flattened)
np.median(arr, axis=0)  # array([4., 7., 2.5])
np.median(arr, axis=1)  # array([3., 5.])

Correct Ways To Get The Median

Pick the approach that fits your data. The core call uses np.median. When NaN values appear, reach for np.nanmedian, which ignores NaN during the calculation. If you work with masked arrays, use np.ma.median. These functions share familiar arguments, so swapping is painless.

Plain Arrays

m = np.median(arr, axis=None, keepdims=False)

This returns a scalar for the whole array or a 1-D result along the chosen axis. The docs list how multiple axes get flattened before computing the statistic.

Ignore NaN Values

m = np.nanmedian(arr, axis=0, keepdims=True)

The function skips NaN entries and returns the median of the remaining values. Handy when data imports bring in missing entries as NaN.

Masked Arrays

mx = np.ma.array([1, 2, 3, 999], mask=[0, 0, 0, 1])
m = np.ma.median(mx)

Masked elements drop out of the computation, which keeps results clean in pipelines that mark sentinel values.

Fixes For Common Setups

Different projects hit this error in different places. Use the swap that matches your stack to stop the crash and keep results stable.

  • Swap The Call Site — Replace arr.median() with np.median(arr). Add axis=... if you need per-row or per-column output.
  • Handle NaN First — Use np.nanmedian(arr) when inputs include missing values. This avoids manual cleanup and keeps the code short.
  • Use Pandas When You Have A Series — A pandas.Series does expose .median(). If your object truly is a Series, keep that call; if it is an ndarray, call the NumPy function.
  • Retain Shape For Broadcasting — Pass keepdims=True so the output aligns with later vectorized steps without extra reshapes.
  • Mind The Pattern — Many AttributeErrors in this area stem from calling module functions as if they were instance methods, such as nan_to_num or append. Call them on the module: np.nan_to_num(x), np.append(x, v).

Safe Patterns For Axes And Shapes

Median across the wrong axis yields odd shapes. A small table keeps the intent clear during a refactor.

Goal Call Result Shape
Single value from whole array np.median(a) () scalar
Column-wise on 2-D np.median(a, axis=0) (n_cols,)
Row-wise with broadcast-friendly dims np.median(a, axis=1, keepdims=True) (n_rows, 1)

The reference explains how flattening works when you pass a sequence of axes, and how keepdims preserves dimensions for later math.

Small Sample With NaN

a = np.array([[1.0, np.nan, 5.0],
              [2.0,  3.0,   4.0]])

np.nanmedian(a)           # 3.0
np.nanmedian(a, axis=0)   # array([1.5, 3. , 4.5])
np.nanmedian(a, axis=1)   # array([3., 3.])

The function ignores NaN and computes the center from the valid numbers. The API mirrors np.median, which keeps your call sites consistent.

AttributeError: ‘NumPy NdArray’ Object Has No Attribute ‘Median’ — Real Code Fixes

This section shows direct swaps that clear the error while keeping results intact. Each swap keeps naming simple and avoids surprise shape changes.

Replace A Direct Method Call

# before
m = arr.median()

# after
m = np.median(arr)

Use the function from the NumPy namespace. The doc page lists the full signature.

Compute Across An Axis

# median of each column
col_m = np.median(arr, axis=0)

# median of each row
row_m = np.median(arr, axis=1)

Pick the axis that matches your grouping. Axis 0 walks rows and returns one value per column. Axis 1 walks columns and returns one value per row.

Skip Missing Values

m = np.nanmedian(arr, axis=0)

When datasets carry NaN, this call avoids a pre-clean step and yields the expected center.

Work With A Masked Array

mx = np.ma.masked_equal(arr, 9999)
m  = np.ma.median(mx)

Masked entries drop out, which keeps downstream math steady.

Leaning On A Series

import pandas as pd

s = pd.Series([1, 2, 3, 4, 5])
m = s.median()            # Series supports .median()

Pandas objects expose .median(), so code that once worked on a Series will fail after converting to an ndarray. Confirm your object type before calling methods. If it’s a NumPy array, prefer the NumPy function.

When Median Lives In Pandas, Not NumPy

Many pipelines start in pandas, then jump to NumPy for speed or scikit-learn steps. During that jump, a Series turns into an ndarray via .to_numpy() or .values. A subsequent .median() then breaks. Two clean fixes exist: keep the Series until you finish the reduction, or call the NumPy function after conversion.

  • Stay In Series — Compute series.median() before converting to a NumPy array for modeling. This keeps index alignment and dtype rules from pandas while you reduce.
  • Convert Then Use NumPy — Convert to an array, then call np.median. This mirrors the function-first pattern used across NumPy’s stats.
# option 1
m1 = df["score"].median()

# option 2
a  = df["score"].to_numpy()
m2 = np.median(a)

Shape-Safe Broadcast Back To A DataFrame

a = df.to_numpy()
med = np.median(a, axis=0, keepdims=True)
df_centered = df - med  # pairs by column without extra reshape

Using keepdims=True returns a row that aligns with a 2-D frame, which avoids extra plumbing. The reference details shape behavior for these flags.

Practical Debugging Checklist

When a pipeline throws this attribute message, run through a short list. Each step removes a common pitfall fast.

  1. Confirm The Type — Print type(obj). If it’s numpy.ndarray, call the function; if it’s a Series, the method call is fine.
  2. Call The Right API — Swap obj.median() for np.median(obj). Use np.nanmedian when inputs contain NaN.
  3. Set The Axis — Decide if you want one value, per column, or per row. Pass axis to match that plan.
  4. Preserve Dimensions — Add keepdims=True if the next step expects a row or column vector.
  5. Scan For Similar Mistakes — If another call reads like an instance method but lives on the module, fix that pattern too. Threads catalog this frequent cause across helpers like nan_to_num.

Reference Snippets You Can Drop In

Use these small pieces as building blocks. Each one avoids the attribute trap and keeps shapes predictable.

Column Medians Then Center

med = np.median(a, axis=0, keepdims=True)
a_centered = a - med

Row Medians For A Robust Score

row_med = np.median(a, axis=1)
score   = np.abs(a - row_med[:, None]).mean()

Ignore NaN In A Single Pass

clean_med = np.nanmedian(a, axis=None)

Each call mirrors the signature in the docs. Keep these patterns near any stats block and you avoid the attribute message altogether. The documentation pages remain the source of truth for arguments and return shapes.

Lastly, note that other array libraries mirror this split between functions and methods. If you port code to JAX, you still call jax.numpy.nanmedian rather than a method on an array object. Knowing the pattern once saves time across stacks.