diff --git a/.gitignore b/.gitignore index 96b1f945870de..82e2eb44e43e7 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,4 @@ doc/source/styled.xlsx doc/source/templates/ env/ doc/source/savefig/ +*my-dev-test.py \ No newline at end of file diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 15c5cc97b8426..86cf9774e2add 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -255,6 +255,6 @@ Other ^^^^^ - :meth: `~pandas.io.formats.style.Styler.background_gradient` now takes a ``text_color_threshold`` parameter to automatically lighten the text color based on the luminance of the background color. This improves readability with dark background colors without the need to limit the background colormap range. (:issue:`21258`) -- +- Bug in :meth:`concat` should maintain dict order when :meth:`concat` is called (:issue:`2151`) - - diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index b36e9b8d900fd..d311f07c144ce 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -1,7 +1,7 @@ """ concat routines """ - +from collections import OrderedDict import numpy as np from pandas import compat, DataFrame, Series, Index, MultiIndex from pandas.core.index import (_get_objs_combined_axis, @@ -250,7 +250,10 @@ def __init__(self, objs, axis=0, join='outer', join_axes=None, if isinstance(objs, dict): if keys is None: - keys = sorted(objs) + if not isinstance(objs, OrderedDict): + keys = sorted(objs) + else: + keys = objs objs = [objs[k] for k in keys] else: objs = list(objs) diff --git a/pandas/tests/reshape/test_concat.py b/pandas/tests/reshape/test_concat.py index dea305d4b3fee..b7b38618be0b3 100644 --- a/pandas/tests/reshape/test_concat.py +++ b/pandas/tests/reshape/test_concat.py @@ -1,3 +1,4 @@ +from collections import OrderedDict from warnings import catch_warnings from itertools import combinations, product @@ -1294,6 +1295,17 @@ def test_concat_rename_index(self): tm.assert_frame_equal(result, exp) assert result.index.names == exp.index.names + def test_concat_with_ordered_dict(self): + # GH 21510 + result = pd.concat(OrderedDict([('First', pd.Series(range(3))), + ('Another', pd.Series(range(4)))])) + index = MultiIndex(levels=[['First', 'Another'], [0, 1, 2, 3]], + labels=[[0, 0, 0, 1, 1, 1, 1], + [0, 1, 2, 0, 1, 2, 3]]) + data = list(range(3)) + list(range(4)) + expected = pd.Series(data, index=index) + tm.assert_series_equal(result, expected) + def test_crossed_dtypes_weird_corner(self): columns = ['A', 'B', 'C', 'D'] df1 = DataFrame({'A': np.array([1, 2, 3, 4], dtype='f8'),