pandas-dev/pandas · error · TypeError

PeriodArray does not allow floating point in construction

Error message

PeriodArray does not allow floating point in construction

What it means

Raised by PeriodArray._from_sequence when the input coerces to a float ndarray that contains any non-NaN value. PeriodArray construction from float is only tolerated when every element is NaN (treated as NaT); meaningful floats are rejected because periods are defined by integer ordinals + freq, not by floating values. This prevents accidentally constructing periods from e.g. decimal years.

Solutions

  1. Convert floats to int ordinals first: pd.array(np.asarray(values, dtype='int64'), dtype='period[M]').
  2. Pass Period scalars or period strings: pd.period_array([pd.Period('2023', freq='Y'), ...]).
  3. Keep all-NaN float arrays if the intent is an all-NaT result (that path is allowed).

Example fix

# before
pd.array([2023.0, 2024.0], dtype='period[Y]')  # raises

# after
pd.array(np.array([2023, 2024], dtype='int64'), dtype='period[Y]')
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def period_array_safe(values, freq):
    arr = np.asarray(values)
    if arr.dtype.kind == 'f':
        if np.isnan(arr).all():
            return pd.period_array([pd.NaT] * len(arr), freq=freq)
        arr = arr.astype('int64', copy=False)
    return pd.array(arr, dtype=f'period[{freq}]')

Type guard

import numpy as np

def is_integer_or_allnan_float(values) -> bool:
    arr = np.asarray(values)
    return arr.dtype.kind in 'iu' or (arr.dtype.kind == 'f' and bool(np.isnan(arr).all()))

Try / catch

try:
    pd.array(values, dtype=f'period[{freq}]')
except TypeError as e:
    if 'floating point' in str(e):
        pd.array(np.asarray(values, dtype='int64'), dtype=f'period[{freq}]')
    else:
        raise

Prevention

When it happens

Trigger: pd.array([2023.0, 2024.0], dtype='period[Y]'); pd.PeriodIndex([1.5, 2.5], freq='M'); feeding a Float64 nullable column into a period constructor without first converting to int ordinals or Period strings.

Common situations: Year-as-float data (2023.5); downstream of nullable integer arrays whose NaNs forced a float cast; CSV columns read as float that semantically represent period ordinals.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/2bb63d31cfa9a852. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/period.py:307

                return scalars.copy()
            return scalars

        if not isinstance(
            scalars, (np.ndarray, list, tuple, ABCSeries, ABCIndex, ExtensionArray)
        ):
            # test_constructor_empty_special has a case with an iter object
            scalars = list(scalars)

        if isinstance(scalars, ExtensionArray) and scalars.dtype.kind in "iu":
            # e.g. masked or arrow-backed integer array; np.asarray would cast
            #  integers-with-NA to float and raise a misleading "floating point"
            #  error below, so route through object dtype to keep the integers.
            scalars = scalars.to_numpy(dtype=object, na_value=NaT)

        arrdata = np.asarray(scalars)
        if arrdata.dtype.kind == "f" and len(arrdata) > 0:
            if not lib.all_nans(arrdata):
                raise TypeError(
                    "PeriodArray does not allow floating point in construction"
                )
            ordinals = np.full(arrdata.shape, iNaT, dtype=np.int64)
            return cls(ordinals, dtype=dtype)

        elif arrdata.dtype.kind in "iu":
            # GH#64227 enforcing means dropping from_calendar_ordinals here and
            #  reading arrdata as ordinals; the object-dtype and Period-scalar
            #  paths in tslibs.period must be enforced at the same time or the
            #  two interpretations diverge again.
            warnings.warn(
                INT_TO_PERIOD_DEPR_MSG,
                Pandas4Warning,
                stacklevel=find_stack_level(),
            )
            arr = arrdata.astype(np.int64, copy=False)
            ordinals = libperiod.from_calendar_ordinals(arr, dtype)  # type: ignore[arg-type]
            return cls(ordinals, dtype=dtype)

View on GitHub (pinned to 3b7651241d)