pandas-dev/pandas · error · ValueError

to_coo requires MultiIndex with nlevels >= 2.

Error message

to_coo requires MultiIndex with nlevels >= 2.

What it means

Thrown by sparse_series_to_coo in pandas/core/arrays/sparse/scipy_sparse.py:157 when the Series index has fewer than 2 levels. COO matrix conversion splits MultiIndex levels between rows and columns, which is meaningless for a single-level or flat index — at minimum one row level and one column level are required.

Source

Thrown at pandas/core/arrays/sparse/scipy_sparse.py:157

    return values, i_coords, j_coords, i_labels, j_labels


def sparse_series_to_coo(
    ss: Series,
    row_levels: Iterable[int] = (0,),
    column_levels: Iterable[int] = (1,),
    sort_labels: bool = False,
) -> tuple[scipy.sparse.coo_matrix, list[IndexLabel], list[IndexLabel]]:
    """
    Convert a sparse Series to a scipy.sparse.coo_matrix using index
    levels row_levels, column_levels as the row and column
    labels respectively. Returns the sparse_matrix, row and column labels.
    """
    import scipy.sparse

    if ss.index.nlevels < 2:
        raise ValueError("to_coo requires MultiIndex with nlevels >= 2.")
    if not ss.index.is_unique:
        raise ValueError(
            "Duplicate index entries are not allowed in to_coo transformation."
        )

    # to keep things simple, only rely on integer indexing (not labels)
    row_levels = [ss.index._get_level_number(x) for x in row_levels]
    column_levels = [ss.index._get_level_number(x) for x in column_levels]

    v, i, j, rows, columns = _to_ijv(
        ss, row_levels=row_levels, column_levels=column_levels, sort_labels=sort_labels
    )
    sparse_matrix = scipy.sparse.coo_matrix(
        (v, (i, j)), shape=(len(rows), len(columns))
    )
    return sparse_matrix, rows, columns

View on GitHub (pinned to 3b7651241d)

Solutions

  1. Rebuild a MultiIndex with at least 2 levels before calling to_coo, e.g. ss.index = pd.MultiIndex.from_arrays([a, b]).
  2. If you genuinely have one level, use a different sparse representation (scipy.sparse.coo_matrix from explicit (data,(i,j)) tuples) rather than pandas to_coo.
  3. Guard the call: if ss.index.nlevels >= 2: ss.sparse.to_coo().

Example fix

// before
s = pd.Series([1,0,2], index=['a','b','c']).astype('Sparse[int]')
s.sparse.to_coo()  # raises

// after
s.index = pd.MultiIndex.from_arrays([['a','b','c'], [0,1,2]])
s.sparse.to_coo()
Defensive patterns

Strategy: validation

Validate before calling

def to_coo_safe(ss, **kw):
    if ss.index.nlevels < 2:
        raise ValueError(f'need MultiIndex with >=2 levels, got {ss.index.nlevels}')
    return ss.sparse.to_coo(**kw)

Type guard

import pandas as pd
def is_multiindex(obj) -> bool:
    return isinstance(obj.index, pd.MultiIndex) and obj.index.nlevels >= 2

Try / catch

null

Prevention

When it happens

Trigger: Calling ss.sparse.to_coo() on a sparse Series with a plain Index or a SingleElement-MultiIndex (nlevels==1). Calling to_coo on a Series whose MultiIndex was collapsed via droplevel(0).

Common situations: User assumes any sparse Series can be COO-converted but only MultiIndexed data qualifies. Index flattening earlier in the pipeline removed the second level.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/928adfa676b93b05. Report an issue: GitHub.