pandas-dev/pandas · error · NotImplementedError
cannot use an invert condition when passing to numexpr
Error message
cannot use an invert condition when passing to numexpr
What it means
Raised by ConditionBinOp.invert in pandas.core.computation.pytables. Conditions (ConditionBinOp) are translated into a numexpr string passed to PyTables; numexpr/PyTables cannot represent an arbitrary negation of a compiled condition, so calling .invert() on a ConditionBinOp raises NotImplementedError. It is triggered when a '~' (or 'not') wraps a condition that is destined for the numexpr path rather than the filter path.
Source
Thrown at pandas/core/computation/pytables.py:383
class JointFilterBinOp(FilterBinOp):
def format(self):
raise NotImplementedError("unable to collapse Joint Filters")
# error: Signature of "evaluate" incompatible with supertype "BinOp"
def evaluate(self) -> Self: # type: ignore[override]
return self
class ConditionBinOp(BinOp):
def __repr__(self) -> str:
return pprint_thing(f"[Condition : [{self.condition}]]")
def invert(self):
"""invert the condition"""
# if self.condition is not None:
# self.condition = "~(%s)" % self.condition
# return self
raise NotImplementedError(
"cannot use an invert condition when passing to numexpr"
)
def format(self):
"""return the actual ne format"""
return self.condition
# error: Signature of "evaluate" incompatible with supertype "BinOp"
def evaluate(self) -> Self | None: # type: ignore[override]
if not self.is_valid:
raise ValueError(f"query term is not valid [{self}]")
# convert values if we are in the table
if not self.is_in_table:
return None
rhs = self.conform(self.rhs)
values = [self.convert_value(v) for v in rhs]View on GitHub (pinned to 71959b8cb9)
Solutions
- Rewrite the negation as a positive condition: '~(price > 100)' -> 'price <= 100'; '~(a == 5)' -> 'a != 5'.
- Read the data and invert in pandas: df = store.get('df'); df[~(df['price'] > 100)].
- If using list membership, prefer the '!=' filter path which does support inversion internally.
Example fix
# before
store.select('df', where='~(price > 100)') # NotImplementedError: cannot use an invert condition when passing to numexpr
# after (rewrite positively)
store.select('df', where='price <= 100')
# or invert in pandas
df = store.get('df')
df[~(df['price'] > 100)] Defensive patterns
Strategy: validation
Validate before calling
import re
def rewrite_inverted_condition(where: str) -> str:
# ~(a > X) -> a <= X ; ~(a < X) -> a >= X ; etc.
m = re.match(r'~\s*\(\s*(\w+)\s*(>=|<=|>|<|==|!=)\s*([^)]+)\s*\)\s*$', where.strip())
if not m:
return where
col, op, val = m.groups()
invert = {'>': '<=', '<': '>=', '>=': '<', '<=': '>', '==': '!=', '!=': '=='}
return f'{col} {invert[op]} {val}'
where = rewrite_inverted_condition(where) Try / catch
try:
store.select('df', where=where)
except NotImplementedError as e:
if 'cannot use an invert condition' in str(e):
df = store.get('df')
result = df[~df.eval(where.replace('~', ''))]
else:
raise Prevention
- Rewrite '~(a OP b)' as the positive inverse (a INVOP b).
- Use '!=' instead of '~(==)' for equality negation.
- Fall back to in-pandas inversion for complex negations.
When it happens
Trigger: store.select('df', where='~(price > 100)') where 'price > 100' compiles to a numexpr condition; store.select('df', where='not (a == 5)') against a condition column. The invert is fine for FilterBinOps but not for conditions.
Common situations: Wanting the complement of a range/equality query; migrating SQL NOT semantics to pytables where; combining '~' with comparison operators.
Related errors
- name {self.name!r} is not defined
- arithmetic operations are not supported inside an HDFStore '
- Cannot compare {conv_val} of type {type(conv_val)} to {kind}
- query term is not valid [{self}]
- passing a filterable condition to a non-table indexer [{self
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/298a4db0d687916a.
Report an issue: GitHub.