diff --git a/pandas/core/frame.py b/pandas/core/frame.py index cd85cce361cb4..a588830d1d584 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -638,10 +638,10 @@ def _can_fast_transpose(self) -> bool: """ Can we transpose this DataFrame without creating any new array objects. """ - if self._data.any_extension_types: + if self._mgr.any_extension_types: # TODO(EA2D) special case would be unnecessary with 2D EAs return False - return len(self._data.blocks) == 1 + return len(self._mgr.blocks) == 1 # ---------------------------------------------------------------------- # Rendering Methods @@ -2872,7 +2872,7 @@ def _get_column_array(self, i: int) -> ArrayLike: Get the values of the i'th column (ndarray or ExtensionArray, as stored in the Block) """ - return self._data.iget_values(i) + return self._mgr.iget_values(i) def _iter_column_arrays(self) -> Iterator[ArrayLike]: """ @@ -4904,7 +4904,7 @@ def _maybe_casted_values(index, labels=None): @doc(NDFrame.isna, klass=_shared_doc_kwargs["klass"]) def isna(self) -> DataFrame: - result = self._constructor(self._data.isna(func=isna)) + result = self._constructor(self._mgr.isna(func=isna)) return result.__finalize__(self, method="isna") @doc(NDFrame.isna, klass=_shared_doc_kwargs["klass"]) @@ -8568,6 +8568,7 @@ def _reduce( ): assert filter_type is None or filter_type == "bool", filter_type + out_dtype = "bool" if filter_type == "bool" else None dtype_is_dt = np.array( [ @@ -8587,10 +8588,9 @@ def _reduce( cols = self.columns[~dtype_is_dt] self = self[cols] - # TODO: Make other agg func handle axis=None properly + # TODO: Make other agg func handle axis=None properly GH#21597 axis = self._get_axis_number(axis) labels = self._get_agg_axis(axis) - constructor = self._constructor assert axis in [0, 1] def func(values): @@ -8599,18 +8599,19 @@ def func(values): else: return op(values, axis=axis, skipna=skipna, **kwds) + def blk_func(values): + if isinstance(values, ExtensionArray): + return values._reduce(name, skipna=skipna, **kwds) + else: + return op(values, axis=1, skipna=skipna, **kwds) + def _get_data() -> DataFrame: if filter_type is None: data = self._get_numeric_data() - elif filter_type == "bool": + else: # GH#25101, GH#24434 + assert filter_type == "bool" data = self._get_bool_data() - else: # pragma: no cover - msg = ( - f"Generating numeric_only data with filter_type {filter_type} " - "not supported." - ) - raise NotImplementedError(msg) return data if numeric_only is not None: @@ -8621,14 +8622,6 @@ def _get_data() -> DataFrame: df = df.T axis = 0 - out_dtype = "bool" if filter_type == "bool" else None - - def blk_func(values): - if isinstance(values, ExtensionArray): - return values._reduce(name, skipna=skipna, **kwds) - else: - return op(values, axis=1, skipna=skipna, **kwds) - # After possibly _get_data and transposing, we are now in the # simple case where we can use BlockManager.reduce res = df._mgr.reduce(blk_func) @@ -8644,11 +8637,10 @@ def blk_func(values): if not self._is_homogeneous_type or self._mgr.any_extension_types: # try to avoid self.values call - if filter_type is None and axis == 0 and len(self) > 0: + if filter_type is None and axis == 0: # operate column-wise # numeric_only must be None here, as other cases caught above - # require len(self) > 0 bc frame_apply messes up empty prod/sum # this can end up with a non-reduction # but not always. if the types are mixed @@ -8684,19 +8676,17 @@ def blk_func(values): with np.errstate(all="ignore"): result = func(values) - if is_object_dtype(result.dtype): + if filter_type == "bool" and notna(result).all(): + result = result.astype(np.bool_) + elif filter_type is None and is_object_dtype(result.dtype): try: - if filter_type is None: - result = result.astype(np.float64) - elif filter_type == "bool" and notna(result).all(): - result = result.astype(np.bool_) + result = result.astype(np.float64) except (ValueError, TypeError): # try to coerce to the original dtypes item by item if we can if axis == 0: result = coerce_to_dtypes(result, data.dtypes) - if constructor is not None: - result = self._constructor_sliced(result, index=labels) + result = self._constructor_sliced(result, index=labels) return result def nunique(self, axis=0, dropna=True) -> Series: