From 9dc4a63edd523d927362a27a0ce46e83faaf2674 Mon Sep 17 00:00:00 2001 From: paulreece Date: Fri, 27 Oct 2023 16:34:25 -0400 Subject: [PATCH] This fix allows a DataFrame to retain key order from a dictionary with only one column instead of sorting them alphabetically. --- doc/source/whatsnew/v2.2.0.rst | 4 ++-- pandas/core/indexes/api.py | 5 ++++- .../frame/constructors/test_from_dict.py | 21 +++++++++++++++++++ pandas/tests/frame/methods/test_rename.py | 5 ++--- .../tests/indexing/multiindex/test_setitem.py | 2 +- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 908027158725dc..34dc35a98cb2b4 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -315,7 +315,7 @@ Bug fixes Categorical ^^^^^^^^^^^ - :meth:`Categorical.isin` raising ``InvalidIndexError`` for categorical containing overlapping :class:`Interval` values (:issue:`34974`) -- Bug in :meth:`CategoricalDtype.__eq__` returning false for unordered categorical data with mixed types (:issue:`55468`) +- Bug in :meth:`Dataframe.from_dict` which would always sort the rows of the created :class:`DataFrame`. (:issue:`55683`) - Datetimelike @@ -327,7 +327,7 @@ Datetimelike - Bug in addition or subtraction of :class:`BusinessDay` offset with ``offset`` attribute to non-nanosecond :class:`Index`, :class:`Series`, or :class:`DataFrame` column giving incorrect results (:issue:`55608`) - Bug in addition or subtraction of :class:`DateOffset` objects with microsecond components to ``datetime64`` :class:`Index`, :class:`Series`, or :class:`DataFrame` columns with non-nanosecond resolution (:issue:`55595`) - Bug in addition or subtraction of very large :class:`Tick` objects with :class:`Timestamp` or :class:`Timedelta` objects raising ``OverflowError`` instead of ``OutOfBoundsTimedelta`` (:issue:`55503`) -- +- Bug in creating a Dataframe using the from_dict method which would alphabetize the rows of the created DataFrame. (:issue:`55683`) Timedelta ^^^^^^^^^ diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index 877b8edb325206..560285bd57a221 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -220,7 +220,10 @@ def union_indexes(indexes, sort: bool | None = True) -> Index: if len(indexes) == 1: result = indexes[0] if isinstance(result, list): - result = Index(sorted(result)) + if not sort: + result = Index(result) + else: + result = Index(sorted(result)) return result indexes, kind = _sanitize_and_check(indexes) diff --git a/pandas/tests/frame/constructors/test_from_dict.py b/pandas/tests/frame/constructors/test_from_dict.py index d78924ff9d046e..845174bbf600e0 100644 --- a/pandas/tests/frame/constructors/test_from_dict.py +++ b/pandas/tests/frame/constructors/test_from_dict.py @@ -200,3 +200,24 @@ def test_from_dict_orient_invalid(self): ) with pytest.raises(ValueError, match=msg): DataFrame.from_dict({"foo": 1, "baz": 3, "bar": 2}, orient="abc") + + def test_from_dict_order_with_single_column(self): + data = { + "alpha": { + "value2": 123, + "value1": 532, + "animal": 222, + "plant": False, + "name": "test", + } + } + result = DataFrame.from_dict( + data, + orient="columns", + ) + expected = DataFrame( + [[123], [532], [222], [False], ["test"]], + index=["value2", "value1", "animal", "plant", "name"], + columns=["alpha"], + ) + tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/frame/methods/test_rename.py b/pandas/tests/frame/methods/test_rename.py index fb70e656814f9b..f35cb21f378bb8 100644 --- a/pandas/tests/frame/methods/test_rename.py +++ b/pandas/tests/frame/methods/test_rename.py @@ -50,13 +50,12 @@ def test_rename(self, float_frame): # index data = {"A": {"foo": 0, "bar": 1}} - # gets sorted alphabetical df = DataFrame(data) renamed = df.rename(index={"foo": "bar", "bar": "foo"}) - tm.assert_index_equal(renamed.index, Index(["foo", "bar"])) + tm.assert_index_equal(renamed.index, Index(["bar", "foo"])) renamed = df.rename(index=str.upper) - tm.assert_index_equal(renamed.index, Index(["BAR", "FOO"])) + tm.assert_index_equal(renamed.index, Index(["FOO", "BAR"])) # have to pass something with pytest.raises(TypeError, match="must pass an index to rename"): diff --git a/pandas/tests/indexing/multiindex/test_setitem.py b/pandas/tests/indexing/multiindex/test_setitem.py index 51b94c3beeb6fc..0eaddd4fbe0a94 100644 --- a/pandas/tests/indexing/multiindex/test_setitem.py +++ b/pandas/tests/indexing/multiindex/test_setitem.py @@ -175,7 +175,7 @@ def test_multiindex_setitem2(self): ) expected = df_orig.copy() - expected.iloc[[0, 2, 3]] *= 2 + expected.iloc[[0, 1, 3]] *= 2 idx = pd.IndexSlice df = df_orig.copy()