diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index 30a828064f812..bf30f2d356b44 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -451,6 +451,7 @@ Reshaping - Fix to ensure all int dtypes can be used in :func:`merge_asof` when using a tolerance value. Previously every non-int64 type would raise an erroneous ``MergeError`` (:issue:`28870`). - Better error message in :func:`get_dummies` when `columns` isn't a list-like value (:issue:`28383`) - Bug :meth:`Series.pct_change` where supplying an anchored frequency would throw a ValueError (:issue:`28664`) +- Bug where :meth:`DataFrame.equals` returned True incorrectly in some cases when two DataFrames had the same columns in different orders (:issue:`28839`) Sparse ^^^^^^ diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index 8a9410c076f9b..0e6ba8a2c2a6a 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -1394,12 +1394,12 @@ def equals(self, other): if len(self.blocks) != len(other.blocks): return False - # canonicalize block order, using a tuple combining the type - # name and then mgr_locs because there might be unconsolidated + # canonicalize block order, using a tuple combining the mgr_locs + # then type name because there might be unconsolidated # blocks (say, Categorical) which can only be distinguished by # the iteration order def canonicalize(block): - return (block.dtype.name, block.mgr_locs.as_array.tolist()) + return (block.mgr_locs.as_array.tolist(), block.dtype.name) self_blocks = sorted(self.blocks, key=canonicalize) other_blocks = sorted(other.blocks, key=canonicalize) diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index dbd84f15d143c..c98bdab0df766 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -1297,3 +1297,10 @@ def test_make_block_no_pandas_array(): result = make_block(arr.to_numpy(), slice(len(arr)), dtype=arr.dtype) assert result.is_integer is True assert result.is_extension is False + + +def test_dataframe_not_equal(): + # see GH28839 + df1 = pd.DataFrame({"a": [1, 2], "b": ["s", "d"]}) + df2 = pd.DataFrame({"a": ["s", "d"], "b": [1, 2]}) + assert df1.equals(df2) is False