AttributeError: ‘Series’ Object Has No Attribute ‘As_Matrix’ | Quick, Safe Fixes

The error appears because pandas removed the as_matrix method from Series; switch to to_numpy(), values, or NumPy helpers.

The message looks scary, but it’s plain version drift. Old snippets used as_matrix(). Modern pandas dropped that method, so a Series no longer exposes it. You still can get a NumPy array cleanly with current, supported calls. This guide shows the fixes, the trade-offs, and the small traps to watch for, with copy-paste code that holds up across releases.

Why You See AttributeError: ‘Series’ Object Has No Attribute ‘As_Matrix’

Quick Context

pandas deprecated as_matrix() in the 0.23 line and removed it in 1.0. From 1.0 onward, calling it raises the exact error you’re seeing on a Series. The official path is .to_numpy(), with .values and np.asarray() as workable options.

In older docs you’ll still find Series.as_matrix and DataFrame.as_matrix, along with a note that the return is an ndarray, not the NumPy matrix class. That history explains why many blog posts still show the discarded call.

Fixing ‘Series’ Object Has No Attribute ‘as_matrix’ In Pandas

Pick the fix that fits your code path. Each option below returns a NumPy array you can feed to scikit-learn, PyTorch, or plain math. Community threads confirm these swaps on recent versions.

  1. Use to_numpy() — The modern, explicit choice. arr = s.to_numpy(). It reads well and matches the direction of the library.
  2. Use values — Short and common in legacy code. arr = s.values. Docs now recommend .to_numpy(), so prefer that in new work.
  3. Use NumPy — Works across versions. arr = np.asarray(s). Many tutorials still teach this form.
  4. Select, Then Convert — Need a subset first? arr = df[cols].to_numpy() or df.loc[:, cols].to_numpy(). Old code sometimes passed columns=[...] into as_matrix(); selecting on the DataFrame preserves that intent.

You may also see the lowercase form in logs: attributeerror: ‘series’ object has no attribute ‘as_matrix’. Same root cause, same fixes.

Use The Right Tool: to_numpy Vs values Vs array

Each option behaves slightly differently, mainly around copying and extension dtypes. Here’s a compact map you can keep handy. The notes mirror current pandas docs.

Call When To Use Notes
Series.to_numpy(dtype=None, copy=False) Default for clear intent May return a view for NumPy dtypes; can copy for extension dtypes.
Series.values Legacy code that still reads well Docs steer you to .to_numpy() for clarity.
np.asarray(s) Library-agnostic paths Lets NumPy decide; handy in cross-project utilities.

Version Check And Refactor Patterns

Check Your Pandas Version

import pandas as pd
print(pd.__version__)
  • < 0.23as_matrix() existed. Upgrade and refactor; staying here blocks modern libraries.
  • 0.23–<1.0 — The method was flagged for removal. Swap calls now.
  • ≥ 1.0 — The method is gone. Use one of the fixes above.

Migration Map From Old Calls

Old Code New Code Why It Works
s.as_matrix() s.to_numpy() Direct Series replacement endorsed by docs.
df.as_matrix(columns=cols) df.loc[:, cols].to_numpy() Replicates the column filter that as_matrix once took.
np.matrix(s) np.asarray(s) or s.to_numpy() Prefer ndarrays; matrix is a legacy subclass.

Match Model Shapes

Many estimators expect 2D (n_samples, n_features). A Series is 1D. Wrap or reshape to meet the contract:

# 1D target y
y = s.to_numpy()

# 2D feature X from a Series
X = s.to_numpy().reshape(-1, 1)

Full Replacement Walkthrough

  1. Search The Codebase — Grep for as_matrix in scripts, notebooks, and utility modules.
  2. Check Call Sites — Note whether the object is a Series or a DataFrame and whether a column list was passed.
  3. Swap The Method — For a Series, use to_numpy(). For a DataFrame with a column subset, select with loc and then convert.
  4. Adjust Shapes — If a downstream call expects 2D input, reshape with .reshape(-1, 1) or build a DataFrame of features.
  5. Add A Tiny Test — Assert the type is np.ndarray and the shape matches expectations.
  6. Run The Pipeline — Execute a small slice of data through the stage that used to fail to confirm the fix.
  7. Commit With Notes — Record that the change removes a call to a deleted pandas API and link to the release notes.

Data Cleaning Before Conversion

Array conversion magnifies messy inputs. A Series with currency symbols, blanks, or mixed decimals drops into an object array. Clean first so numeric math does not stall.

  • Strip Units — Remove symbols with str.replace, then cast with astype("float64").
  • Handle Missing — Fill with a sentinel or drop rows before conversion.
  • Guard Types — Validate with pd.to_numeric(..., errors="raise") so bad rows surface early.

Working Examples

# Clean, then convert
s = pd.Series(["10.5", "11.0", "12.2", None, "14.1"])
s = pd.to_numeric(s, errors="coerce").fillna(0.0)
arr = s.to_numpy()

API Notes You Can Reference

  • to_numpy() Availability — Added around the 0.24 release and present in current pandas.
  • values Attribute — Still present, with docs nudging users to .to_numpy().
  • DataFrame.to_numpy() — Works like the Series version, with the same dtype and copy parameters.

Where This Error Pops Up

  • Old tutorials — Many posts and notebooks still show as_matrix(). Copying code from those sources triggers the message on pandas 1.x and 2.x.
  • Legacy utilities — Small helpers in a codebase can still call the removed method. Search for the string and swap in a single place.
  • Model pipelines — Feature extraction that returns a Series can hit the method during a transform step. Convert to an array at the boundary.
  • Plotting — Some homegrown wrappers feed arrays to matplotlib. Convert once when passing data in.
  • CSV loaders — After reading text data, a pipeline that casts to numbers can end up with mixed dtypes; convert with a dtype= hint.

Edge Cases And Pitfalls To Watch

  • Mixed Dtypes — A Series with strings and numbers may coerce to object. If you need floats, pass dtype="float64" or clean data first.
  • Datetime And Timezone — Converting a timezone-aware Series can materialize datetime64[ns, tz] into object-typed arrays in some flows. Keep timezone handling explicit and convert once near the boundary of your code.
  • Categorical And Sparse — Extension dtypes can trigger a copy on .to_numpy(). That’s expected and yields a regular NumPy array ready for numeric work.
  • Copy Versus View — With plain NumPy dtypes, .to_numpy(copy=False) may expose a view. In-place edits then reflect back into the Series; avoid mutation unless you intend it.
  • Rows Versus Columns — The removed API’s columns=[...] belonged to DataFrame calls. Slice on the frame, then convert.

Keep It Future-Proof

Avoid NumPy’s matrix Class

The old name as_matrix can tempt you toward np.matrix. Skip that path. The NumPy docs and training sites steer everyday work to ndarrays, not the matrix subclass. Use regular arrays and the @ operator for linear algebra.

Deep Notes For Stable Code

Memory and speed: .to_numpy() can return a view when the Series already holds a NumPy buffer. That saves allocations. With extension types, a copy can occur, which trades a little speed for compatibility. Both behaviors are spelled out in the docs.

Series.array vs to_numpy: when you want a reference to the underlying data for extension types, use Series.array. When you want a plain NumPy array, use .to_numpy(). The docs make the distinction clear.

Library upgrades: pinned environments sometimes surface this break after a minor bump. If you must hold a legacy version for a specific pipeline, log the constraint and schedule a refactor to the modern calls. Threads across projects report that the swap is a one-liner in most cases.

Performance Tips

  • Avoid Extra Copies — Call to_numpy(copy=False) when you only need a read-only view of numeric data.
  • Vectorize — Push heavy math into NumPy after conversion to keep Python loops out of hot paths.
  • Batch I/O — Convert once per operation rather than inside tight loops that already iterate over rows.

Lint And CI Safeguards

Once you fix the call sites, prevent regressions. Add a pre-commit hook or CI job that rejects fresh uses of the removed name. A tiny regex catch keeps the change sticky across branches.

# .github/workflows/scan.yml
name: scan
on: [push, pull_request]
jobs:
  grep:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Block as_matrix
        run: |
          if git grep -n "as_matrix\\s*\\(" ; then
            echo "Found deprecated pandas call"; exit 1
          fi

This kind of guard costs almost nothing and saves a round of debugging later.

Team Playbook Snippet

  • Use to_numpy() for pandas-to-NumPy boundaries.
  • Slice First on DataFrames, then convert.
  • Prefer ndarrays and the @ operator for linear algebra.
  • Avoid Hidden Copies by passing copy=False when safe.
  • Document Shapes with type hints and small asserts to keep training code predictable.
  • Document Version Bumps — Note pandas upgrades in your CHANGELOG entries.

Troubleshooting Checklist

  • Confirm the version — Print pd.__version__. If it’s 1.0 or newer, as_matrix is gone.
  • Replace the call — Use s.to_numpy(), s.values, or np.asarray(s).
  • Reshape if needed — Models that need 2D input want .reshape(-1, 1).
  • Select columns first — For multi-column input, slice the DataFrame, then convert.
  • Avoid np.matrix — Stick with ndarrays and the @ operator.

Recap You Can Trust

The string attributeerror: ‘series’ object has no attribute ‘as_matrix’ points to a removed API, not a broken install. Swap the call to to_numpy(), keep any column selection on the DataFrame side, and reshape when a library requests 2D input. If you want the raw NumPy form in one line, np.asarray(s) stays tidy. Stick with ndarrays and the @ operator for linear algebra. These choices match current docs and avoid churn across pandas releases.

One last note before you close the tab: when porting a notebook from an older course or blog, read the first few import cells slowly and replace any as_matrix usage right away. You’ll avoid a mid-run failure and you’ll keep your runtime aimed at experiments. The small, explicit swaps in this guide are stable across pandas 1.x and 2.x, and align with the library’s own recommendations. If a teammate asks why the change matters, point them to the 1.0 release notes that removed the method.

Once you swap those calls, the message fades and your data pipes stay clean across releases. That’s all you need. Ship the fix once, and get back to building with confidence today.

It keeps your pipelines fast. Always.