microsoft/qlib · error · NotImplementedError
please implement _align_indices func
Error message
please implement _align_indices func
What it means
IndexData is a base class; binary operations (+, -, *, / via BinaryOps) call _align_indices to bring the other operand's index to match self. The base implementation is deliberately a NotImplementedError stub — only SingleData and MultiData provide real alignment logic. Hitting it means an IndexData subclass (or the base class itself) was used in arithmetic without an alignment strategy.
Solutions
- Use SingleData (1-D) or MultiData (2-D) instead of the raw IndexData base class.
- If you subclass IndexData, implement _align_indices(self, other) -> IndexData that reindexes `other` onto self.indices and returns it.
- Alternatively pre-align manually with reindex()/reindexall() before doing arithmetic, which bypasses _align_indices.
Example fix
// before c = IndexData(a.data, *a.indices) + b # NotImplementedError // after c = SingleData(a.data, a.index) + b.reindex(a.index) # concrete classes align fine
Defensive patterns
Strategy: type-guard
Validate before calling
from qlib.utils.index_data import SingleData, MultiData, IndexData assert type(a) is not IndexData and type(b) is not IndexData, 'use SingleData/MultiData for arithmetic'
Type guard
def supports_alignment(obj) -> bool:
return type(obj).__name__ in ('SingleData', 'MultiData') or type(obj)._align_indices is not IndexData._align_indices Try / catch
try:
c = a + b
except NotImplementedError:
b = b.reindex(a.index)
c = SingleData(a.data, a.index) + b Prevention
- Never instantiate the IndexData base class for values used in arithmetic.
- When subclassing IndexData, implement _align_indices (and reindex) before writing any binary-op tests.
When it happens
Trigger: Instantiating IndexData directly or subclassing it (e.g. for a custom 1-D/2-D variant) and then applying +, -, *, / between two instances; also any code path that calls obj._align_indices(other) on a bare IndexData.
Common situations: Extending qlib's index-data containers for a new data shape; importing IndexData instead of SingleData/MultiData by mistake; upgrading qlib versions where the alignment contract moved into subclass methods.
Related errors
- Please implement `save_obj`
- Please implement the `exists` method
- Please implement the `list` method
- Please implement the `load_obj` method
- Please implement the `remove` method
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/6ea6d5715cb462e5.
Report an issue: GitHub.
Appendix: source
Thrown at qlib/utils/index_data.py:435
# NOTE: this tries to behave like a numpy array to be compatible with numpy aggregating function like nansum and nanmean
return self.iloc[args]
def _align_indices(self, other: "IndexData") -> "IndexData":
"""
Align all indices of `other` to `self` before performing the arithmetic operations.
This function will return a new IndexData rather than changing data in `other` inplace
Parameters
----------
other : "IndexData"
the index in `other` is to be changed
Returns
-------
IndexData:
the data in `other` with index aligned to `self`
"""
raise NotImplementedError(f"please implement _align_indices func")
def sort_index(self, axis=0, inplace=True):
assert inplace, "Only support sorting inplace now"
self.indices[axis], sorted_idx = self.indices[axis].sort()
self.data = np.take(self.data, sorted_idx, axis=axis)
# The code below could be simpler like methods in __getattribute__
def __invert__(self):
return self.__class__(~self.data.astype(bool), *self.indices)
def abs(self):
"""get the abs of data except np.nan."""
tmp_data = np.absolute(self.data)
return self.__class__(tmp_data, *self.indices)
def replace(self, to_replace: Dict[np.number, np.number]):
assert isinstance(to_replace, dict)
tmp_data = self.data.copy()View on GitHub (pinned to 79633dd950)