{"record":{"id":"430c64d51fdf0b1c","repo":"pandas-dev/pandas","slug":"n-dimensional-objects-where-n-2-are-not-suppor","errorCode":null,"errorMessage":"N-dimensional objects, where N > 2, are not supported with eval","messagePattern":"N-dimensional objects, where N > 2, are not supported with eval","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/ops.py","lineNumber":123,"sourceCode":"    def __call__(self, *args, **kwargs):\n        return self.value\n\n    def evaluate(self, *args, **kwargs) -> Term:\n        return self\n\n    def _resolve_name(self):\n        local_name = str(self.local_name)\n        is_local = self.is_local\n        if local_name in self.env.scope and isinstance(\n            self.env.scope[local_name], type\n        ):\n            is_local = False\n\n        res = self.env.resolve(local_name, is_local=is_local)\n        self.update(res)\n\n        if hasattr(res, \"ndim\") and isinstance(res.ndim, int) and res.ndim > 2:\n            raise NotImplementedError(\n                \"N-dimensional objects, where N > 2, are not supported with eval\"\n            )\n        return res\n\n    def update(self, value) -> None:\n        \"\"\"\n        search order for local (i.e., @variable) variables:\n\n        scope, key_variable\n        [('locals', 'local_name'),\n         ('globals', 'local_name'),\n         ('locals', 'key'),\n         ('globals', 'key')]\n        \"\"\"\n        key = self.name\n\n        # if it's a variable name (otherwise a constant)\n        if isinstance(key, str):","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/computation/ops.py#L105-L141","documentation":"Raised by Term._resolve_name in pandas.core.computation.ops when a name resolved from the eval/query scope has ndim > 2. pandas' eval engine only operates on scalars, Series (1D), and DataFrames (2D); anything of higher dimensionality (e.g. a 3D numpy array or an xarray.DataArray) cannot be mapped to a term. It is raised as NotImplementedError after the value is resolved from locals/globals. The check uses hasattr(res,'ndim') and isinstance(res.ndim, int).","triggerScenarios":"Calling pd.eval(), DataFrame.eval(), or DataFrame.query() with a local variable (via @var) or a column whose value is an object with ndim > 2, e.g. pd.eval('@a', local_dict={'a': np.zeros((2,2,2))}) or df.query('a > 0') where column 'a' holds 3D ndarrays per row.","commonSituations":"Passing a 3D numpy array, an xarray.DataArray, or a stacked Panel-like object into an eval expression. Also occurs when a column was constructed from nested arrays whose elements are themselves multi-dimensional, or when migrating old Panel-based code to modern pandas.","solutions":["Reduce the operand to 1D/2D before eval: reshape with .ravel(), .reshape(-1), .squeeze(), or stack the array so ndim <= 2.","If the goal is element-wise math on an N-D array, skip pd.eval and use numpy/ufuncs directly (e.g. np.sin(a)).","If the N-D object is a column of arrays, flatten/explode it first (df['a'].explode() or np.stack) so each cell is scalar.","For multi-index DataFrames, reset_index() or stack/unstack to bring the frame back to 2D before querying."],"exampleFix":"# before\nimport numpy as np, pandas as pd\na = np.zeros((2, 2, 2))\npd.eval('@a + 1', local_dict={'a': a})  # NotImplementedError\n\n# after\npd.eval('@a_flat + 1', local_dict={'a_flat': a.ravel()})\n# or just use numpy:\na + 1","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef safe_eval_operand(value):\n    ndim = getattr(value, 'ndim', None)\n    if isinstance(ndim, int) and ndim > 2:\n        raise ValueError(f'operand has ndim={ndim}; pandas.eval only supports ndim<=2')\n    return value\n\n# before pd.eval('@a + 1', local_dict={'a': a}):\nsafe_eval_operand(a)","typeGuard":"from typing import Any\nimport numpy as np\n\ndef is_eval_safe_array(obj: Any) -> bool:\n    ndim = getattr(obj, 'ndim', None)\n    return isinstance(ndim, int) and ndim <= 2\n","tryCatchPattern":"try:\n    result = pd.eval(expr, local_dict=locals())\nexcept NotImplementedError as e:\n    if 'N-dimensional' in str(e):\n        # flatten or fall back to numpy\n        result = None\n    else:\n        raise","preventionTips":["Keep eval/query operands to scalars, Series, or 2D DataFrames.","Pre-flatten N-D arrays with .ravel()/.reshape(-1) before passing as @locals.","For N-D math, use numpy ufuncs directly instead of pd.eval."],"tags":["pandas","eval","ndarray","dimensionality"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}