diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py index 825757ddffee4..57df9ed9ed2d7 100644 --- a/pandas/core/arrays/_mixins.py +++ b/pandas/core/arrays/_mixins.py @@ -23,7 +23,6 @@ from pandas.util._validators import validate_fillna_kwargs from pandas.core.dtypes.common import is_dtype_equal -from pandas.core.dtypes.inference import is_array_like from pandas.core.dtypes.missing import array_equivalent from pandas.core import missing @@ -275,15 +274,7 @@ def fillna( value, method = validate_fillna_kwargs(value, method) mask = self.isna() - - # TODO: share this with EA base class implementation - if is_array_like(value): - if len(value) != len(self): - raise ValueError( - f"Length of 'value' does not match. Got ({len(value)}) " - f" expected {len(self)}" - ) - value = value[mask] + value = missing.check_value_size(value, mask, len(self)) if mask.any(): if method is not None: diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index edc8fa14ca142..3b80c0b189108 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -44,7 +44,6 @@ from pandas.core.dtypes.cast import maybe_cast_to_extension_array from pandas.core.dtypes.common import ( - is_array_like, is_dtype_equal, is_list_like, is_scalar, @@ -58,13 +57,15 @@ ) from pandas.core.dtypes.missing import isna -from pandas.core import ops +from pandas.core import ( + missing, + ops, +) from pandas.core.algorithms import ( factorize_array, isin, unique, ) -from pandas.core.missing import get_fill_func from pandas.core.sorting import ( nargminmax, nargsort, @@ -696,18 +697,11 @@ def fillna(self, value=None, method=None, limit=None): value, method = validate_fillna_kwargs(value, method) mask = self.isna() - - if is_array_like(value): - if len(value) != len(self): - raise ValueError( - f"Length of 'value' does not match. Got ({len(value)}) " - f"expected {len(self)}" - ) - value = value[mask] + value = missing.check_value_size(value, mask, len(self)) if mask.any(): if method is not None: - func = get_fill_func(method) + func = missing.get_fill_func(method) new_values = func(self.astype(object), limit=limit, mask=mask) new_values = self._from_sequence(new_values, dtype=self.dtype) else: diff --git a/pandas/core/arrays/string_arrow.py b/pandas/core/arrays/string_arrow.py index e2b0ad372bf88..8441b324515f3 100644 --- a/pandas/core/arrays/string_arrow.py +++ b/pandas/core/arrays/string_arrow.py @@ -33,13 +33,13 @@ is_integer_dtype, is_scalar, ) +from pandas.core import missing from pandas.core.arraylike import OpsMixin from pandas.core.arrays.base import ExtensionArray from pandas.core.indexers import ( check_array_indexer, validate_indices, ) -from pandas.core.missing import get_fill_func try: import pyarrow as pa @@ -380,18 +380,11 @@ def fillna(self, value=None, method=None, limit=None): value, method = validate_fillna_kwargs(value, method) mask = self.isna() - - if is_array_like(value): - if len(value) != len(self): - raise ValueError( - f"Length of 'value' does not match. Got ({len(value)}) " - f"expected {len(self)}" - ) - value = value[mask] + value = missing.check_value_size(value, mask, len(self)) if mask.any(): if method is not None: - func = get_fill_func(method) + func = missing.get_fill_func(method) new_values = func(self.to_numpy(object), limit=limit, mask=mask) new_values = self._from_sequence(new_values) else: diff --git a/pandas/core/missing.py b/pandas/core/missing.py index 9ae5f7d1b7497..0b77a6d821c6d 100644 --- a/pandas/core/missing.py +++ b/pandas/core/missing.py @@ -29,6 +29,7 @@ from pandas.core.dtypes.cast import infer_dtype_from from pandas.core.dtypes.common import ( ensure_float64, + is_array_like, is_integer_dtype, is_numeric_v_string_like, needs_i8_conversion, @@ -39,6 +40,21 @@ from pandas import Index +def check_value_size(value, mask: np.ndarray, length: int): + """ + Validate the size of the values passed to ExtensionArray.fillna. + """ + if is_array_like(value): + if len(value) != length: + raise ValueError( + f"Length of 'value' does not match. Got ({len(value)}) " + f" expected {length}" + ) + value = value[mask] + + return value + + def mask_missing(arr: ArrayLike, values_to_mask) -> np.ndarray: """ Return a masking array of same size/shape as arr