pandas-dev/pandas · error · TypeError
cannot subtract {type(other).__name__} from {type(self).__na
Error message
cannot subtract {type(other).__name__} from {type(self).__name__} What it means
Raised by _sub_periodlike when self.dtype is not PeriodDtype. Subtracting a Period (or PeriodArray) is only defined for PeriodArray operands (yielding an object ndarray of DateOffsets); doing it against DatetimeArray or TimedeltaArray is rejected.
Source
Thrown at pandas/core/arrays/datetimelike.py:1241
# like a timedelta.
# For datetime64 dtypes by convention we treat NaT as a datetime, so
# this subtraction returns a timedelta64 dtype.
# For period dtype, timedelta64 is a close-enough return dtype.
result = np.empty(self.shape, dtype=np.int64)
result.fill(iNaT)
if self.dtype.kind in "mM":
# We can retain unit in dtype
self = cast("DatetimeArray| TimedeltaArray", self)
return result.view(f"timedelta64[{self.unit}]")
else:
return result.view("timedelta64[ns]")
@final
def _sub_periodlike(self, other: Period | PeriodArray) -> npt.NDArray[np.object_]:
# If the operation is well-defined, we return an object-dtype ndarray
# of DateOffsets. Null entries are filled with pd.NaT
if not isinstance(self.dtype, PeriodDtype):
raise TypeError(
f"cannot subtract {type(other).__name__} from {type(self).__name__}"
)
self = cast("PeriodArray", self)
self._check_compatible_with(other)
other_i8, o_mask = self._get_i8_values_and_mask(other)
new_i8_data = add_overflowsafe(self.asi8, np.asarray(-other_i8, dtype="i8"))
new_data = np.array([self.freq.base * x for x in new_i8_data])
if o_mask is None:
# i.e. Period scalar
mask = self._isnan
else:
# i.e. PeriodArray
mask = self._isnan | o_mask
new_data[mask] = NaT
return new_dataView on GitHub (pinned to 71959b8cb9)
Solutions
- Convert the Period to a Timestamp first: idx - period.to_timestamp().
- For PeriodIndex, use idx - other_period to get a DateOffset result.
- Add the appropriate DateOffset (negative) instead of subtracting a Period from a DatetimeIndex.
- Check isinstance(idx.dtype, pd.PeriodDtype) before subtracting a Period.
Example fix
// before
out = datetime_idx - pd.Period('2020-01', 'M') # TypeError
// after
out = datetime_idx - pd.Period('2020-01', 'M').to_timestamp() Defensive patterns
Strategy: type-guard
Validate before calling
from pandas.api.types import is_period_dtype
if not is_period_dtype(idx.dtype):
out = idx - period.to_timestamp()
else:
out = idx - period Type guard
def accepts_period_subtraction(idx) -> bool:
from pandas.api.types import is_period_dtype
return is_period_dtype(idx.dtype) Try / catch
try:
out = idx - period
except TypeError as e:
if 'cannot subtract' in str(e) and 'Period' in str(e):
out = idx - period.to_timestamp()
else:
raise Prevention
- Only PeriodArray supports subtracting a Period operand.
- Convert Period to Timestamp before datetime arithmetic.
- Guard on isinstance(idx.dtype, pd.PeriodDtype).
When it happens
Trigger: DatetimeIndex - pd.Period(...) or TimedeltaIndex - PeriodArray, dispatched via __sub__ line 1398-1399 into _sub_periodlike at line 1237; the PeriodDtype check at line 1240 fires.
Common situations: Mixing Period and datetime columns in subtraction; assuming Period behaves like a datetime or offset.
Related errors
- cannot add Period to a {type(self).__name__}
- Cannot add {type(self).__name__} and {type(NaT).__name__}
- cannot subtract {type(self).__name__} from {other.dtype}
- Cannot compare types {!r} and {!r}
- '{self.dtype}' does not have duration components
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/89cfe4c058eead9d.
Report an issue: GitHub.