Skip to content

unchecked MultiIndex row index results in Pandas Error #2049

@chillerb

Description

@chillerb

Please make sure these conditions are met

  • I have checked that this issue has not already been reported.
  • I have confirmed this bug exists on the latest version of anndata.
  • (optional) I have confirmed this bug exists on the master branch of anndata.

Report

While anndata checks for multiindex columns, multiindex rows go unchecked and raise a pandas error due to the type cast.

Code:

import anndata as ad
import pandas as pd

df = pd.DataFrame({"x": [1,2,3]}, index=pd.MultiIndex.from_tuples([("a", 1), ("b", 2), ("c", 3)]))
ad.AnnData(df)

Traceback:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[49], line 5
      2 import pandas as pd
      4 df = pd.DataFrame({"x": [1,2,3]}, index=pd.MultiIndex.from_tuples([("a", 1), ("b", 2), ("c", 3)]))
----> 5 ad.AnnData(df)

File ~/micromamba/envs/dev/lib/python3.12/site-packages/legacy_api_wrap/__init__.py:82, in legacy_api.<locals>.wrapper.<locals>.fn_compatible(*args_all, **kw)
     79 @wraps(fn)
     80 def fn_compatible(*args_all: P.args, **kw: P.kwargs) -> R:
     81     if len(args_all) <= n_positional:
---> 82         return fn(*args_all, **kw)
     84     args_pos: P.args
     85     args_pos, args_rest = args_all[:n_positional], args_all[n_positional:]

File ~/micromamba/envs/dev/lib/python3.12/site-packages/anndata/_core/anndata.py:242, in AnnData.__init__(self, X, obs, var, uns, obsm, varm, layers, raw, dtype, shape, filename, filemode, asview, obsp, varp, oidx, vidx)
    240     self._init_as_view(X, oidx, vidx)
    241 else:
--> 242     self._init_as_actual(
    243         X=X,
    244         obs=obs,
    245         var=var,
    246         uns=uns,
    247         obsm=obsm,
    248         varm=varm,
    249         raw=raw,
    250         layers=layers,
    251         dtype=dtype,
    252         shape=shape,
    253         obsp=obsp,
    254         varp=varp,
    255         filename=filename,
    256         filemode=filemode,
    257     )

File ~/micromamba/envs/dev/lib/python3.12/site-packages/anndata/_core/anndata.py:424, in AnnData._init_as_actual(self, X, obs, var, uns, obsm, varm, varp, obsp, raw, layers, dtype, shape, filename, filemode)
    421     source = "shape"
    423 # annotations
--> 424 self._obs = _gen_dataframe(
    425     obs, ["obs_names", "row_names"], source=source, attr="obs", length=n_obs
    426 )
    427 self._var = _gen_dataframe(
    428     var, ["var_names", "col_names"], source=source, attr="var", length=n_vars
    429 )
    431 # now we can verify if indices match!

File ~/micromamba/envs/dev/lib/python3.12/functools.py:912, in singledispatch.<locals>.wrapper(*args, **kw)
    908 if not args:
    909     raise TypeError(f'{funcname} requires at least '
    910                     '1 positional argument')
--> 912 return dispatch(args[0].__class__)(*args, **kw)

File ~/micromamba/envs/dev/lib/python3.12/site-packages/anndata/_core/aligned_df.py:87, in _gen_dataframe_df(anno, index_names, source, attr, length)
     85     msg = "Transforming to str index."
     86     warnings.warn(msg, ImplicitModificationWarning, stacklevel=2)
---> 87     anno.index = anno.index.astype(str)
     88 if not len(anno.columns):
     89     anno.columns = anno.columns.astype(str)

File ~/micromamba/envs/dev/lib/python3.12/site-packages/pandas/core/indexes/multi.py:3892, in MultiIndex.astype(self, dtype, copy)
   3890     raise NotImplementedError(msg)
   3891 if not is_object_dtype(dtype):
-> 3892     raise TypeError(
   3893         "Setting a MultiIndex dtype to anything other than object "
   3894         "is not supported"
   3895     )
   3896 if copy is True:
   3897     return self._view()

TypeError: Setting a MultiIndex dtype to anything other than object is not supported

Versions

| Package    | Version |
| ---------- | ------- |
| pandas     | 2.3.0   |
| pytometry  | 0.1.4   |
| numpy      | 1.26.4  |
| matplotlib | 3.10.3  |
| pyhere     | 1.0.3   |
| anndata    | 0.12.0  |
| FlowKit    | 1.2.3   |

| Dependency         | Version                |
| ------------------ | ---------------------- |
| typing_extensions  | 4.14.0                 |
| packaging          | 24.2                   |
| statsmodels        | 0.14.4                 |
| lxml               | 6.0.0                  |
| certifi            | 2025.6.15 (2025.06.15) |
| setuptools         | 80.9.0                 |
| prompt_toolkit     | 3.0.51                 |
| idna               | 3.10                   |
| xyzservices        | 2025.4.0               |
| bokeh              | 3.7.3                  |
| multipledispatch   | 0.6.0                  |
| scipy              | 1.15.2                 |
| platformdirs       | 4.3.8                  |
| pure_eval          | 0.2.3                  |
| Jinja2             | 3.1.6                  |
| comm               | 0.2.2                  |
| pyct               | 0.5.0                  |
| zarr               | 3.1.0                  |
| matplotlib-inline  | 0.1.7                  |
| scikit-learn       | 1.7.0                  |
| psutil             | 7.0.0                  |
| pyarrow            | 19.0.1                 |
| ipywidgets         | 8.1.7                  |
| networkx           | 3.5                    |
| tornado            | 6.5.1                  |
| Brotli             | 1.1.0                  |
| numcodecs          | 0.16.1                 |
| cycler             | 0.12.1                 |
| six                | 1.17.0                 |
| msgpack            | 1.1.1                  |
| MarkupSafe         | 3.0.2                  |
| natsort            | 8.4.0                  |
| astroid            | 3.3.10                 |
| cloudpickle        | 3.1.1                  |
| PyYAML             | 6.0.2                  |
| pycparser          | 2.22                   |
| threadpoolctl      | 3.6.0                  |
| pyparsing          | 3.2.3                  |
| legacy-api-wrap    | 1.4.1                  |
| cffi               | 1.17.1                 |
| ipykernel          | 6.29.5                 |
| FlowUtils          | 1.1.0                  |
| Pygments           | 2.19.2                 |
| session-info2      | 0.1.2                  |
| jaraco.collections | 5.1.0                  |
| llvmlite           | 0.44.0                 |
| contourpy          | 1.3.2                  |
| kiwisolver         | 1.4.8                  |
| readfcs            | 1.1.8                  |
| executing          | 2.2.0                  |
| fsspec             | 2025.5.1               |
| jaraco.context     | 5.3.0                  |
| xarray             | 2025.7.1               |
| more-itertools     | 10.3.0                 |
| traitlets          | 5.14.3                 |
| zstandard          | 0.23.0                 |
| jaraco.text        | 3.12.1                 |
| debugpy            | 1.8.14                 |
| anytree            | 2.13.0 (2.12.1)        |
| stack_data         | 0.6.3                  |
| param              | 2.2.1                  |
| donfig             | 0.8.1.post1            |
| h5py               | 3.14.0                 |
| jupyter_core       | 5.8.1                  |
| decorator          | 5.2.1                  |
| jupyter_client     | 8.6.3                  |
| requests           | 2.32.4                 |
| scanpy             | 1.11.3                 |
| joblib             | 1.5.1                  |
| toolz              | 1.0.0                  |
| fcsparser          | 0.2.8                  |
| wcwidth            | 0.2.13                 |
| patsy              | 1.0.1                  |
| numba              | 0.61.2                 |
| crc32c             | 2.7.1                  |
| PySocks            | 1.7.1                  |
| datashader         | 0.18.1                 |
| jaraco.functools   | 4.0.1                  |
| python-dateutil    | 2.9.0.post0            |
| charset-normalizer | 3.4.2                  |
| pyzmq              | 27.0.0                 |
| ipython            | 9.4.0                  |
| parso              | 0.8.4                  |
| colorama           | 0.4.6                  |
| asttokens          | 3.0.0                  |
| pytz               | 2025.2                 |
| jedi               | 0.19.2                 |
| FlowIO             | 1.3.0                  |
| seaborn            | 0.13.2                 |
| pillow             | 11.3.0                 |
| urllib3            | 2.5.0                  |

| Component | Info                                                                           |
| --------- | ------------------------------------------------------------------------------ |
| Python    | 3.12.11 | packaged by conda-forge | (main, Jun  4 2025, 14:45:31) [GCC 13.3.0] |
| OS        | Linux-5.15.0-142-generic-x86_64-with-glibc2.36                                 |
| Updated   | 2025-07-24 11:53                                                               |

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions