diff --git a/python/cudf/cudf/core/accessors/base_accessor.py b/python/cudf/cudf/core/accessors/base_accessor.py index d3f28140cb6..0e30709fd23 100644 --- a/python/cudf/cudf/core/accessors/base_accessor.py +++ b/python/cudf/cudf/core/accessors/base_accessor.py @@ -98,7 +98,14 @@ def _return_or_inplace( # type: ignore[misc] index=self._parent.index, # type: ignore[union-attr] attrs=self._parent.attrs, # type: ignore[union-attr] ) - if len(table) == 0: + keys = ( + tuple(table.keys()) if hasattr(table, "keys") else () + ) + if len(table) == 0 or ( + keys + and all(isinstance(k, int) for k in keys) + and tuple(keys) == tuple(range(len(keys))) + ): df._data.rangeindex = True return df elif isinstance(self._parent, cudf.Series): diff --git a/python/cudf/cudf/core/dataframe.py b/python/cudf/cudf/core/dataframe.py index 42c5a0c63b5..0fab4b10b78 100644 --- a/python/cudf/cudf/core/dataframe.py +++ b/python/cudf/cudf/core/dataframe.py @@ -2126,6 +2126,15 @@ def _concat( # Reassign index and column names if objs[0]._data.multiindex: out._set_columns_like(objs[0]._data) + elif ( + all(obj._data.rangeindex for obj in objs) + and all( + tuple(obj._column_names) == tuple(range(obj._num_columns)) + for obj in objs + ) + and tuple(names) == tuple(range(len(names))) + ): + out.columns = cudf.RangeIndex(len(names)) else: out.columns = names if not ignore_index: @@ -2419,6 +2428,9 @@ def _fill_same_ca_attributes( else: raise ValueError("other must be a DataFrame or Series.") + if isinstance(column_names_list, pd.MultiIndex): + ca_attributes["multiindex"] = True + ca_attributes["level_names"] = tuple(column_names_list.names) sorted_dict = {key: operands[key] for key in column_names_list} return sorted_dict, index, ca_attributes return operands, index, ca_attributes @@ -4805,6 +4817,23 @@ def join( df.index.name = ( None if self.index.name != other.index.name else self.index.name ) + + # Preserve a CategoricalIndex columns axis when both inputs share the + # same categorical dtype on their column labels (matches pandas). + self_pd_cols = self._data.to_pandas_index + other_pd_cols = other._data.to_pandas_index + if ( + isinstance(self_pd_cols, pd.CategoricalIndex) + and isinstance(other_pd_cols, pd.CategoricalIndex) + and self_pd_cols.dtype == other_pd_cols.dtype + ): + df.columns = pd.CategoricalIndex( + list(self_pd_cols) + list(other_pd_cols), + dtype=self_pd_cols.dtype, + name=self_pd_cols.name + if self_pd_cols.name == other_pd_cols.name + else None, + ) return df @_performance_tracking @@ -6369,7 +6398,15 @@ def quantile( if len(res) == 0: res = column_empty(row_count=len(qs), dtype=ser.dtype) result[k] = res - result = DataFrame._from_data(result, attrs=self.attrs) + result_ca = ColumnAccessor( + result, + multiindex=data_df._data.multiindex, + level_names=data_df._data.level_names, + rangeindex=data_df._data.rangeindex, + label_dtype=data_df._data.label_dtype, + verify=False, + ) + result = DataFrame._from_data(result_ca, attrs=self.attrs) if q_is_number and numeric_only: result = result.fillna(np.nan).iloc[0] @@ -7233,7 +7270,12 @@ def cudf_dtype_from_pydata_dtype(dtype): for label, dtype in self._dtypes if cudf_dtype_from_pydata_dtype(dtype) in inclusion ] - return self.loc[:, to_select] + result = self.loc[:, to_select] + if not to_select and self._data.rangeindex: + # Preserve RangeIndex columns through an empty selection so that + # downstream operations match pandas' column metadata. + result._data.rangeindex = True + return result @ioutils.doc_to_parquet() def to_parquet( diff --git a/python/cudf/cudf/core/groupby/groupby.py b/python/cudf/cudf/core/groupby/groupby.py index 0ad04470a5f..4e11595dcb0 100644 --- a/python/cudf/cudf/core/groupby/groupby.py +++ b/python/cudf/cudf/core/groupby/groupby.py @@ -1111,12 +1111,27 @@ def agg(self, func=None, *args, engine=None, engine_kwargs=None, **kwargs): if cast_dtype is not None: result_col = result_col.astype(cast_dtype) data[key] = result_col - data = ColumnAccessor(data, multiindex=multilevel) + from cudf.core.dataframe import DataFrame + + # Preserve the column axis label-dtype/level_names from the source + # DataFrame so that aggregations such as ``nunique`` keep the column + # axis name (matching pandas behavior). + if ( + not multilevel + and isinstance(self.obj, DataFrame) + and self.obj._data.level_names != (None,) + ): + data = ColumnAccessor( + data, + multiindex=False, + level_names=self.obj._data.level_names, + label_dtype=self.obj._data.label_dtype, + ) + else: + data = ColumnAccessor(data, multiindex=multilevel) if not multilevel: data = data.rename_levels({np.nan: None}, level=0) - from cudf.core.dataframe import DataFrame - result = DataFrame._from_data(data, index=result_index) if self._sort: @@ -2753,6 +2768,8 @@ def _scan_fill( ) -> DataFrameOrSeries: """Internal implementation for `ffill` and `bfill`""" values = self.grouping.values + from cudf.core.dataframe import DataFrame + result = self.obj._from_data( dict( zip( @@ -2762,6 +2779,33 @@ def _scan_fill( ) ) ) + # Pandas' groupby.ffill/bfill builds the result columns via a ``take`` + # on the input columns, which converts integer-valued column labels + # to object dtype. Reproduce that here so column metadata matches. + if ( + isinstance(result, DataFrame) + and isinstance(self.obj, DataFrame) + and result._num_columns < self.obj._num_columns + ): + source_pd_cols = self.obj._data.to_pandas_index + if ( + source_pd_cols.dtype.kind in {"i", "u"} + or source_pd_cols.dtype == object + ): + try: + positions = [ + source_pd_cols.get_loc(c) for c in result._column_names + ] + except (KeyError, TypeError): + positions = None + if positions is not None: + taken = source_pd_cols.take(positions) + if ( + not isinstance(taken, pd.MultiIndex) + and taken.dtype != object + ): + taken = taken.astype(object) + result.columns = taken return self._mimic_pandas_order(result) def ffill(self, limit: int | None = None): diff --git a/python/cudf/cudf/core/indexed_frame.py b/python/cudf/cudf/core/indexed_frame.py index 57ef45930dc..f3cdd26d20d 100644 --- a/python/cudf/cudf/core/indexed_frame.py +++ b/python/cudf/cudf/core/indexed_frame.py @@ -4013,11 +4013,13 @@ def _reindex( index = index if index is not None else df.index + label_dtype = None if column_names is None: names = list(df._column_names) level_names = self._data.level_names multiindex = self._data.multiindex rangeindex = self._data.rangeindex + label_dtype = self._data.label_dtype elif isinstance(column_names, (pd.Index, cudf.Index)): if isinstance(column_names, (pd.MultiIndex, cudf.MultiIndex)): multiindex = True @@ -4034,6 +4036,12 @@ def _reindex( rangeindex = isinstance( column_names, (pd.RangeIndex, cudf.RangeIndex) ) + if not rangeindex: + label_dtype = ( + column_names.dtype + if isinstance(column_names, pd.Index) + else column_names.to_pandas().dtype + ) level_names = tuple(column_names.names) else: names = column_names @@ -4066,6 +4074,7 @@ def _reindex( multiindex=multiindex, level_names=level_names, rangeindex=rangeindex, + label_dtype=label_dtype, ), index=index, attrs=self.attrs, diff --git a/python/cudf/cudf/core/reshape.py b/python/cudf/cudf/core/reshape.py index 10d55391a7e..d44d1c0c88f 100644 --- a/python/cudf/cudf/core/reshape.py +++ b/python/cudf/cudf/core/reshape.py @@ -129,7 +129,10 @@ def _normalize_series_and_dataframe( name = obj.name if name is None: if axis == 0: - name = 0 + # Preserve "unnamed" semantics so the resulting frame has + # a RangeIndex columns object (matching pandas). + objs[idx] = obj.to_frame() + continue else: name = sr_name sr_name += 1 @@ -1063,12 +1066,39 @@ def pivot( index_data = index_data.get_level_values(0) else: index_data = cudf.Index(index_data) + # An entirely empty input pivots to an empty result. Pandas uses the + # default ``object`` dtype for the resulting index axis in that case; + # mirror this so index metadata (dtype/inferred_type) matches. + if ( + len(data) == 0 + and not isinstance(index_data, cudf.MultiIndex) + and isinstance(index_data.dtype, pd.StringDtype) + ): + index_data = cudf.Index( + pd.Index([], name=index_data.name, dtype=object) + ) column_data = data.loc[:, columns] + # When `columns` is a scalar but the source DataFrame has a MultiIndex on + # the row axis, ``loc`` may return a 2-D selection in cuDF. Treat the + # selection as 1-D so we end up with a flat Index of column labels. + if is_scalar(columns) and column_data.ndim == 2: + column_data = column_data.iloc[:, 0] if column_data.ndim == 2: column_data = cudf.MultiIndex.from_frame(column_data) else: column_data = cudf.Index(column_data) + # An entirely empty input pivots to an empty result. Pandas reports the + # default ``object`` dtype for the resulting columns axis in that case; + # mirror this so column metadata (dtype/inferred_type) matches. + if ( + len(data) == 0 + and not isinstance(column_data, cudf.MultiIndex) + and isinstance(column_data.dtype, pd.StringDtype) + ): + column_data = cudf.Index( + pd.Index([], name=column_data.name, dtype=object) + ) # Create a DataFrame composed of columns from both # columns and index diff --git a/python/cudf/cudf/core/single_column_frame.py b/python/cudf/cudf/core/single_column_frame.py index ddf725ac766..345aee05a41 100644 --- a/python/cudf/cudf/core/single_column_frame.py +++ b/python/cudf/cudf/core/single_column_frame.py @@ -254,11 +254,22 @@ def tolist(self) -> None: def _to_frame(self, name: Hashable, index: Index | None) -> DataFrame: """Helper function for Series.to_frame, Index.to_frame""" + unnamed_default = False + col_name: Hashable if name is no_default: - col_name = 0 if self.name is None else self.name + if self.name is None: + col_name = 0 + unnamed_default = True + else: + col_name = self.name else: col_name = name - ca = ColumnAccessor({col_name: self._column}, verify=False) + ca = ColumnAccessor( + {col_name: self._column}, + multiindex=isinstance(col_name, tuple), + rangeindex=unnamed_default, + verify=False, + ) # TODO: Avoid accessing DataFrame from the top level namespace return cudf.DataFrame._from_data(ca, index=index) diff --git a/python/cudf/cudf/pandas/scripts/conftest-patch.py b/python/cudf/cudf/pandas/scripts/conftest-patch.py index 47f0e4b25a2..80788859507 100644 --- a/python/cudf/cudf/pandas/scripts/conftest-patch.py +++ b/python/cudf/cudf/pandas/scripts/conftest-patch.py @@ -723,7 +723,6 @@ def pytest_unconfigure(config): "tests/base/test_constructors.py::TestConstruction::test_constructor_datetime_outofbound[Series-object-string]": "Failed: DID NOT RAISE ", "tests/base/test_conversion.py::test_array[index-arr3-_left]": "TODO: Add a reason for failure", "tests/base/test_conversion.py::test_array[index-arr4-_sparse_values]": "TODO: Add a reason for failure", - "tests/base/test_conversion.py::test_array[series-arr3-_left]": "TODO: Add a reason for failure", "tests/base/test_conversion.py::test_array[series-arr4-_sparse_values]": "TODO: Add a reason for failure", "tests/base/test_conversion.py::test_to_numpy[array-False-arr1-expected1-False]": "AssertionError: numpy array are different", "tests/base/test_conversion.py::test_to_numpy[array-True-arr1-expected1-False]": "AssertionError: numpy array are different", @@ -1577,7 +1576,6 @@ def pytest_unconfigure(config): "tests/extension/test_arrow.py::test_setitem_float_nan_is_na[False]": "Failed: DID NOT RAISE ", "tests/extension/test_arrow.py::test_setitem_float_nan_is_na[True]": "assert nan is ", "tests/extension/test_arrow.py::test_str_extract_non_symbolic": "TODO: Add a reason for failure", - "tests/extension/test_arrow.py::test_str_partition": "AssertionError: DataFrame.columns are different", "tests/extension/test_arrow.py::test_str_repeat_unsupported": "TODO: Add a reason for failure", "tests/extension/test_arrow.py::test_str_replace_unsupported[pat-b]": "TODO: Add a reason for failure", "tests/extension/test_arrow.py::test_timestamp_reduction_consistency[ms-max]": "AssertionError: assert 'us' == 'ms'", @@ -1640,28 +1638,6 @@ def pytest_unconfigure(config): "tests/extension/test_interval.py::TestIntervalArray::test_grouping_grouper": "AssertionError: ndarray Expected type , found instead", "tests/extension/test_interval.py::TestIntervalArray::test_in_numeric_groupby": "TODO: Add a reason for failure", "tests/extension/test_interval.py::TestIntervalArray::test_is_extension_array_dtype": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[BooleanDtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[BooleanDtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Float32Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Float32Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Float64Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Float64Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int16Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int16Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int32Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int32Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int64Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int64Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int8Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[Int8Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt16Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt16Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt32Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt32Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt64Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt64Dtype-python]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt8Dtype-c]": "TODO: Add a reason for failure", - "tests/extension/test_masked.py::TestMaskedArrays::test_EA_types[UInt8Dtype-python]": "TODO: Add a reason for failure", "tests/extension/test_masked.py::TestMaskedArrays::test_accumulate_series[UInt16Dtype-cumprod-False]": "TODO: Add a reason for failure", "tests/extension/test_masked.py::TestMaskedArrays::test_accumulate_series[UInt16Dtype-cumprod-True]": "TODO: Add a reason for failure", "tests/extension/test_masked.py::TestMaskedArrays::test_accumulate_series[UInt16Dtype-cumsum-False]": "TODO: Add a reason for failure", @@ -1908,10 +1884,6 @@ def pytest_unconfigure(config): "tests/extension/test_numpy.py::TestNumpyExtensionArray::test_value_counts_with_normalize[object]": "TODO: Add a reason for failure", "tests/extension/test_period.py::Test2DCompat::test_copy_order[2D]": "TODO: Add a reason for failure", "tests/extension/test_period.py::Test2DCompat::test_copy_order[D]": "TODO: Add a reason for failure", - "tests/extension/test_period.py::TestPeriodArray::test_EA_types[2D-c]": "TODO: Add a reason for failure", - "tests/extension/test_period.py::TestPeriodArray::test_EA_types[2D-python]": "TODO: Add a reason for failure", - "tests/extension/test_period.py::TestPeriodArray::test_EA_types[D-c]": "TODO: Add a reason for failure", - "tests/extension/test_period.py::TestPeriodArray::test_EA_types[D-python]": "TODO: Add a reason for failure", "tests/extension/test_period.py::TestPeriodArray::test_astype_own_type[2D-False]": "TODO: Add a reason for failure", "tests/extension/test_period.py::TestPeriodArray::test_astype_own_type[D-False]": "TODO: Add a reason for failure", "tests/extension/test_period.py::TestPeriodArray::test_astype_str[2D]": "AssertionError: Attributes of Series are different", @@ -1940,22 +1912,6 @@ def pytest_unconfigure(config): "tests/extension/test_sparse.py::TestSparseArray::test_unary_ufunc_dunder_equivalence[nan-absolute]": "TODO: Add a reason for failure", "tests/extension/test_sparse.py::TestSparseArray::test_unary_ufunc_dunder_equivalence[nan-negative]": "TODO: Add a reason for failure", "tests/extension/test_sparse.py::TestSparseArray::test_unary_ufunc_dunder_equivalence[nan-positive]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[pyarrow]-False-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[pyarrow]-False-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[pyarrow]-True-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[pyarrow]-True-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[python]-False-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[python]-False-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[python]-True-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=str[python]-True-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[pyarrow]-False-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[pyarrow]-False-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[pyarrow]-True-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[pyarrow]-True-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[python]-False-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[python]-False-python]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[python]-True-c]": "TODO: Add a reason for failure", - "tests/extension/test_string.py::TestStringArray::test_EA_types[string=string[python]-True-python]": "TODO: Add a reason for failure", "tests/extension/test_string.py::TestStringArray::test_arith_series_with_array[string=str[python]-False-__add__]": "AssertionError: Attributes of Series are different", "tests/extension/test_string.py::TestStringArray::test_arith_series_with_array[string=str[python]-True-__add__]": "AssertionError: Attributes of Series are different", "tests/extension/test_string.py::TestStringArray::test_arith_series_with_array[string=string[pyarrow]-False-__radd__]": "TODO: Add a reason for failure", @@ -2235,7 +2191,6 @@ def pytest_unconfigure(config): "tests/frame/methods/test_interpolate.py::TestDataFrameInterpolate::test_interpolate_empty_df": "assert Empty DataFrame\nColumns: []\nIndex: [] is Empty DataFrame\nColumns: []\nIndex: []", "tests/frame/methods/test_interpolate.py::TestDataFrameInterpolate::test_interpolate_inplace[DataFrame]": "TODO: Add a reason for failure", "tests/frame/methods/test_interpolate.py::TestDataFrameInterpolate::test_interpolate_inplace[Series]": "TODO: Add a reason for failure", - "tests/frame/methods/test_join.py::TestDataFrameJoin::test_frame_join_categorical_index": "AssertionError: DataFrame.columns are different", "tests/frame/methods/test_join.py::TestDataFrameJoin::test_join": "TODO: Add a reason for failure", "tests/frame/methods/test_map.py::test_map": "TODO: Add a reason for failure", "tests/frame/methods/test_map.py::test_map_datetimelike[datetime-val0]": "AssertionError: assert '2013-01-01 00:00:00.000000' == '2013-01-01 00:00:00'", @@ -2261,7 +2216,6 @@ def pytest_unconfigure(config): "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_datetime[ns]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_datetime[s]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_datetime[us]": "TODO: Add a reason for failure", - "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_empty_no_columns[linear-single]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_empty_no_columns[nearest-table]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_empty_no_rows_dt64[linear-single]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestDataFrameQuantile::test_quantile_multi_empty[linear-single]": "TODO: Add a reason for failure", @@ -2288,17 +2242,10 @@ def pytest_unconfigure(config): "tests/frame/methods/test_quantile.py::TestQuantileExtensionDtype::test_quantile_ea_with_na[Float64-Series]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestQuantileExtensionDtype::test_quantile_ea_with_na[Int64-DataFrame]": "TODO: Add a reason for failure", "tests/frame/methods/test_quantile.py::TestQuantileExtensionDtype::test_quantile_ea_with_na[Int64-Series]": "TODO: Add a reason for failure", - "tests/frame/methods/test_quantile.py::test_multi_quantile_numeric_only_retains_columns": "AssertionError: DataFrame.columns are different", "tests/frame/methods/test_rank.py::TestRank::test_rank": "AssertionError: numpy array are different", "tests/frame/methods/test_rank.py::TestRank::test_rank_string_dtype[string[pyarrow]-Int64]": "TODO: Add a reason for failure", "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex": "TODO: Add a reason for failure", "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_axis_style_raises": "TODO: Add a reason for failure", - "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx0-CategoricalIndex]": "AssertionError: DataFrame.columns are different", - "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx0-Index]": "AssertionError: DataFrame.columns are different", - "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx1-CategoricalIndex]": "AssertionError: DataFrame.columns are different", - "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx1-Index]": "AssertionError: DataFrame.columns are different", - "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx3-CategoricalIndex]": "AssertionError: DataFrame.columns are different", - "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx3-Index]": "AssertionError: DataFrame.columns are different", "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx4-CategoricalIndex]": "AssertionError: DataFrame are different", "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx4-Index]": "AssertionError: DataFrame are different", "tests/frame/methods/test_reindex.py::TestDataFrameSelectReindex::test_reindex_empty[cat_idx5-CategoricalIndex]": "AssertionError: DataFrame are different", @@ -2486,8 +2433,6 @@ def pytest_unconfigure(config): "tests/frame/test_api.py::TestDataFrameMisc::test_set_flags[Series-None]": "TODO: Add a reason for failure", "tests/frame/test_api.py::TestDataFrameMisc::test_set_flags[Series-True]": "TODO: Add a reason for failure", "tests/frame/test_api.py::TestDataFrameMisc::test_tab_completion": "TODO: Add a reason for failure", - "tests/frame/test_arithmetic.py::TestFrameArithmetic::test_arithmetic_midx_cols_different_dtypes_different_order[numexpr]": "TODO: Add a reason for failure", - "tests/frame/test_arithmetic.py::TestFrameArithmetic::test_arithmetic_midx_cols_different_dtypes_different_order[python]": "TODO: Add a reason for failure", "tests/frame/test_arithmetic.py::TestFrameArithmetic::test_binop_other[numexpr-pow-True-bool]": "TODO: Add a reason for failure", "tests/frame/test_arithmetic.py::TestFrameArithmetic::test_binop_other[numexpr-sub-True-bool]": "TODO: Add a reason for failure", "tests/frame/test_arithmetic.py::TestFrameArithmetic::test_binop_other[numexpr-truediv-True-bool]": "TODO: Add a reason for failure", @@ -2518,8 +2463,6 @@ def pytest_unconfigure(config): "tests/frame/test_arithmetic.py::test_arithmetic_multiindex_align[python]": "TODO: Add a reason for failure", "tests/frame/test_arithmetic.py::test_arithmetic_multiindex_column_align[numexpr]": "AssertionError: DataFrame.columns are different", "tests/frame/test_arithmetic.py::test_arithmetic_multiindex_column_align[python]": "AssertionError: DataFrame.columns are different", - "tests/frame/test_arithmetic.py::test_arithmetic_multiindex_column_align_with_fillvalue[numexpr]": "AssertionError: DataFrame.columns are different", - "tests/frame/test_arithmetic.py::test_arithmetic_multiindex_column_align_with_fillvalue[python]": "AssertionError: DataFrame.columns are different", "tests/frame/test_arithmetic.py::test_bool_frame_mult_float[numexpr]": "TODO: Add a reason for failure", "tests/frame/test_arithmetic.py::test_bool_frame_mult_float[python]": "TODO: Add a reason for failure", "tests/frame/test_arithmetic.py::test_dataframe_operation_with_non_numeric_types[numexpr-df1-object]": "AssertionError: DataFrame.iloc[:, 1] (column name='b') are different", @@ -3436,7 +3379,6 @@ def pytest_unconfigure(config): "tests/groupby/test_groupby.py::test_group_on_two_row_multiindex_returns_one_tuple_key": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_all_nan_groups_drop": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_column_index_name_lost[shift]": "TODO: Add a reason for failure", - "tests/groupby/test_groupby.py::test_groupby_column_index_name_lost[sum]": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_crash_on_nunique": "AssertionError: DataFrame.columns are different", "tests/groupby/test_groupby.py::test_groupby_cumsum_mask[Float32-False-val1]": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_cumsum_mask[Float64-False-val1]": "TODO: Add a reason for failure", @@ -3460,7 +3402,6 @@ def pytest_unconfigure(config): "tests/groupby/test_groupby.py::test_groupby_dropna_with_nunique_unique": "AssertionError: Attributes of DataFrame.iloc[:, 0] (column name='('partner', 'nunique')') are different", "tests/groupby/test_groupby.py::test_groupby_dtype_inference_empty": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_groups_in_BaseGrouper": "TODO: Add a reason for failure", - "tests/groupby/test_groupby.py::test_groupby_level_mapper": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_level_nonmulti": "TODO: Add a reason for failure", "tests/groupby/test_groupby.py::test_groupby_multiindex_not_lexsorted[False]": "AssertionError: assert not True", "tests/groupby/test_groupby.py::test_groupby_multiindex_not_lexsorted[True]": "AssertionError: assert not True", @@ -3575,11 +3516,8 @@ def pytest_unconfigure(config): "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-NoneType-NoneType-object-False]": "AssertionError: DataFrame.index are different", "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-NoneType-NoneType-object-True]": "AssertionError: Series.index are different", "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-NoneType-float0-None-False]": "TODO: Add a reason for failure", - "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-NoneType-float0-None-True]": "TODO: Add a reason for failure", "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-NoneType-float1-None-False]": "TODO: Add a reason for failure", - "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-NoneType-float1-None-True]": "TODO: Add a reason for failure", "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-float0-NoneType-None-False]": "TODO: Add a reason for failure", - "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-float0-NoneType-None-True]": "TODO: Add a reason for failure", "tests/groupby/test_groupby_dropna.py::test_null_is_null_for_dtype[True-float1-NoneType-None-False]": "TODO: Add a reason for failure", "tests/groupby/test_groupby_subclass.py::test_groupby_preserves_metadata": "TODO: Add a reason for failure", "tests/groupby/test_groupby_subclass.py::test_groupby_preserves_subclass[all-obj0]": "TODO: Add a reason for failure", @@ -3624,24 +3562,13 @@ def pytest_unconfigure(config): "tests/groupby/test_grouping.py::TestGrouping::test_evaluate_with_empty_groups[agg-expected1]": "TODO: Add a reason for failure", "tests/groupby/test_grouping.py::TestGrouping::test_evaluate_with_empty_groups[apply-expected2]": "TODO: Add a reason for failure", "tests/groupby/test_grouping.py::TestGrouping::test_groupby_apply_empty_with_group_keys_false": "AssertionError: DataFrame are different", - "tests/groupby/test_grouping.py::TestGrouping::test_groupby_level[False]": "TODO: Add a reason for failure", - "tests/groupby/test_grouping.py::TestGrouping::test_groupby_level[True]": "TODO: Add a reason for failure", "tests/groupby/test_grouping.py::TestGrouping::test_groupby_level_index_value_all_na": "TODO: Add a reason for failure", "tests/groupby/test_grouping.py::TestGrouping::test_groupby_multiindex_partial_indexing_equivalence": "TODO: Add a reason for failure", "tests/groupby/test_grouping.py::TestGrouping::test_groupby_tuple_keys_handle_multiindex": "TypeError: unhashable type: 'list'", "tests/groupby/test_grouping.py::TestGrouping::test_grouper_creation_bug": "AssertionError: DataFrame are different", "tests/groupby/test_grouping.py::TestGrouping::test_multiindex_columns_empty_level": "TODO: Add a reason for failure", - "tests/groupby/test_grouping.py::TestGrouping::test_multiindex_negative_level": "TODO: Add a reason for failure", "tests/groupby/test_grouping.py::TestSelection::test_indices_grouped_by_tuple_with_lambda": "TODO: Add a reason for failure", "tests/groupby/test_indexing.py::test_multiindex": "TODO: Add a reason for failure", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[False-False-bfill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[False-False-ffill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[False-True-bfill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[False-True-ffill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[True-False-bfill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[True-False-ffill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[True-True-bfill]": "AssertionError: DataFrame.columns are different", - "tests/groupby/test_missing.py::test_ffill_handles_nan_groups[True-True-ffill]": "AssertionError: DataFrame.columns are different", "tests/groupby/test_missing.py::test_groupby_column_index_name_lost_fill_funcs[bfill]": "AssertionError: Index are different", "tests/groupby/test_missing.py::test_groupby_column_index_name_lost_fill_funcs[ffill]": "AssertionError: Index are different", "tests/groupby/test_missing.py::test_indices_with_missing": "TODO: Add a reason for failure", @@ -4256,7 +4183,6 @@ def pytest_unconfigure(config): "tests/indexes/interval/test_constructors.py::TestFromBreaks::test_constructor_pass_closed[breaks3]": "TODO: Add a reason for failure", "tests/indexes/interval/test_constructors.py::TestFromBreaks::test_constructor_pass_closed[breaks4]": "TODO: Add a reason for failure", "tests/indexes/interval/test_constructors.py::TestFromBreaks::test_generic_errors": "TODO: Add a reason for failure", - "tests/indexes/interval/test_constructors.py::TestFromBreaks::test_left_right_dont_share_data": "TODO: Add a reason for failure", "tests/indexes/interval/test_constructors.py::TestFromTuples::test_constructor_pass_closed[breaks0]": "TODO: Add a reason for failure", "tests/indexes/interval/test_constructors.py::TestFromTuples::test_constructor_pass_closed[breaks2]": "TODO: Add a reason for failure", "tests/indexes/interval/test_constructors.py::TestFromTuples::test_constructor_pass_closed[breaks3]": "TODO: Add a reason for failure", @@ -4296,7 +4222,6 @@ def pytest_unconfigure(config): "tests/indexes/multi/test_constructors.py::test_from_arrays_respects_none_names": "TODO: Add a reason for failure", "tests/indexes/multi/test_constructors.py::test_from_frame_dtype_fidelity": "TODO: Add a reason for failure", "tests/indexes/multi/test_constructors.py::test_multiindex_inference_consistency": "TODO: Add a reason for failure", - "tests/indexes/multi/test_conversion.py::test_to_frame_column_rangeindex": "AssertionError: Index are different", "tests/indexes/multi/test_conversion.py::test_to_frame_dtype_fidelity": "TODO: Add a reason for failure", "tests/indexes/multi/test_copy.py::test_copy": "TODO: Add a reason for failure", "tests/indexes/multi/test_copy.py::test_copy_deep_false_retains_id": "TODO: Add a reason for failure", @@ -4589,8 +4514,6 @@ def pytest_unconfigure(config): "tests/indexes/test_common.py::TestCommon::test_to_frame[uint8-new_name]": "TODO: Add a reason for failure", "tests/indexes/test_common.py::test_ndarray_compat_properties[multi]": "TODO: Add a reason for failure", "tests/indexes/test_common.py::test_ndarray_compat_properties[tuples]": "TODO: Add a reason for failure", - "tests/indexes/test_common.py::test_to_frame_column_rangeindex": "AssertionError: Index are different", - "tests/indexes/test_common.py::test_to_frame_name_tuple_multiindex": "AssertionError: DataFrame.columns are different", "tests/indexes/test_datetimelike.py::TestDatetimeLike::test_argsort_matches_array[simple_index1]": "TODO: Add a reason for failure", "tests/indexes/test_datetimelike.py::TestDatetimeLike::test_argsort_matches_array[simple_index2]": "TODO: Add a reason for failure", "tests/indexes/test_index_new.py::TestIndexConstructorInference::test_constructor_datetimes_mixed_tzs": "AssertionError: Index are different", @@ -4890,7 +4813,6 @@ def pytest_unconfigure(config): "tests/indexing/test_at.py::TestAtErrors::test_at_applied_for_rows": "Failed: DID NOT RAISE ", "tests/indexing/test_at.py::test_at_timezone": "TODO: Add a reason for failure", "tests/indexing/test_categorical.py::TestCategoricalIndex::test_getitem_row_categorical_with_nan_bool": "AssertionError: Series are different", - "tests/indexing/test_categorical.py::TestCategoricalIndex::test_ix_categorical_index": "TODO: Add a reason for failure", "tests/indexing/test_categorical.py::TestCategoricalIndex::test_ix_categorical_index_non_unique[False]": "AssertionError: DataFrame.index are different", "tests/indexing/test_categorical.py::TestCategoricalIndex::test_loc_getitem_with_non_string_categories[False-idx_values17]": "TODO: Add a reason for failure", "tests/indexing/test_categorical.py::TestCategoricalIndex::test_loc_getitem_with_non_string_categories[False-idx_values28]": "TODO: Add a reason for failure", @@ -5892,7 +5814,6 @@ def pytest_unconfigure(config): "tests/reshape/concat/test_concat.py::test_concat_ignore_empty_object_float[object-datetime64[ns]]": "AssertionError: Attributes of DataFrame.iloc[:, 0] (column name='foo') are different", "tests/reshape/concat/test_concat.py::test_concat_ignore_empty_object_float[object-float64]": "AssertionError: Attributes of DataFrame.iloc[:, 0] (column name='foo') are different", "tests/reshape/concat/test_concat.py::test_concat_ignore_empty_object_float[object-int64]": "TODO: Add a reason for failure", - "tests/reshape/concat/test_concat.py::test_concat_with_series_and_frame_returns_rangeindex_columns": "AssertionError: DataFrame.columns are different", "tests/reshape/concat/test_datetimes.py::TestTimezoneConcat::test_concat_multiindex_with_tz": "AssertionError: DataFrame.index level [0] are different", "tests/reshape/concat/test_datetimes.py::test_concat_float_datetime64": "TODO: Add a reason for failure", "tests/reshape/concat/test_empty.py::TestEmptyConcat::test_concat_empty_dataframe_dtypes": "TODO: Add a reason for failure", @@ -6168,7 +6089,6 @@ def pytest_unconfigure(config): "tests/reshape/test_melt.py::TestWideToLong::test_invalid_separator": "TODO: Add a reason for failure", "tests/reshape/test_melt.py::TestWideToLong::test_invalid_suffixtype": "TODO: Add a reason for failure", "tests/reshape/test_melt.py::TestWideToLong::test_raise_of_column_name_value": "TODO: Add a reason for failure", - "tests/reshape/test_pivot.py::TestPivot::test_pivot_empty": "AssertionError: DataFrame.index are different", "tests/reshape/test_pivot.py::TestPivot::test_pivot_empty_dataframe_period_dtype[D]": "AssertionError: DataFrame.index are different", "tests/reshape/test_pivot.py::TestPivot::test_pivot_empty_dataframe_period_dtype[M]": "AssertionError: DataFrame.index are different", "tests/reshape/test_pivot.py::TestPivot::test_pivot_empty_dataframe_period_dtype[Q]": "AssertionError: DataFrame.index are different", @@ -6211,7 +6131,6 @@ def pytest_unconfigure(config): "tests/reshape/test_pivot.py::TestPivotTable::test_pivot_with_tz[s-True]": "AssertionError: DataFrame.index are different", "tests/reshape/test_pivot.py::TestPivotTable::test_pivot_with_tz[us-False]": "AssertionError: DataFrame.index are different", "tests/reshape/test_pivot.py::TestPivotTable::test_pivot_with_tz[us-True]": "AssertionError: DataFrame.index are different", - "tests/reshape/test_pivot_multilevel.py::test_pivot_df_multiindex_index_none": "AssertionError: DataFrame.columns are different", "tests/reshape/test_pivot_multilevel.py::test_pivot_list_like_columns[input_index1-input_columns1-values-expected_values1-expected_columns1-expected_index1]": "TODO: Add a reason for failure", "tests/reshape/test_pivot_multilevel.py::test_pivot_list_like_columns[input_index3-input_columns3-values-expected_values3-expected_columns3-expected_index3]": "TODO: Add a reason for failure", "tests/reshape/test_pivot_multilevel.py::test_pivot_list_like_columns[lev4-input_columns0-values-expected_values0-expected_columns0-expected_index0]": "TODO: Add a reason for failure",