From 3b932285ed3728708612fbe4a080ca863a72817b Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 28 Jan 2019 09:31:55 -0600 Subject: [PATCH] Fixed itertuples usage in to_dict (#24965) * Fixed itertuples usage in to_dict Closes https://github.com/pandas-dev/pandas/issues/24940 Closes https://github.com/pandas-dev/pandas/issues/24939 --- doc/source/whatsnew/v0.24.1.rst | 7 +++++++ pandas/core/frame.py | 15 +++++++++------ pandas/tests/frame/test_convert_to.py | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/doc/source/whatsnew/v0.24.1.rst b/doc/source/whatsnew/v0.24.1.rst index 3ac2ed73ea53f6..de33ce64c15979 100644 --- a/doc/source/whatsnew/v0.24.1.rst +++ b/doc/source/whatsnew/v0.24.1.rst @@ -15,6 +15,13 @@ Whats New in 0.24.1 (February XX, 2019) These are the changes in pandas 0.24.1. See :ref:`release` for a full changelog including other versions of pandas. +.. _whatsnew_0241.regressions: + +Fixed Regressions +^^^^^^^^^^^^^^^^^ + +- Bug in :meth:`DataFrame.itertuples` with ``records`` orient raising an ``AttributeError`` when the ``DataFrame`` contained more than 255 columns (:issue:`24939`) +- Bug in :meth:`DataFrame.itertuples` orient converting integer column names to strings prepended with an underscore (:issue:`24940`) .. _whatsnew_0241.enhancements: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index b4f79bda255170..28c6f3c23a3ced 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -847,7 +847,7 @@ def itertuples(self, index=True, name="Pandas"): ---------- index : bool, default True If True, return the index as the first element of the tuple. - name : str, default "Pandas" + name : str or None, default "Pandas" The name of the returned namedtuples or None to return regular tuples. @@ -1290,23 +1290,26 @@ def to_dict(self, orient='dict', into=dict): ('columns', self.columns.tolist()), ('data', [ list(map(com.maybe_box_datetimelike, t)) - for t in self.itertuples(index=False)] - ))) + for t in self.itertuples(index=False, name=None) + ]))) elif orient.lower().startswith('s'): return into_c((k, com.maybe_box_datetimelike(v)) for k, v in compat.iteritems(self)) elif orient.lower().startswith('r'): + columns = self.columns.tolist() + rows = (dict(zip(columns, row)) + for row in self.itertuples(index=False, name=None)) return [ into_c((k, com.maybe_box_datetimelike(v)) - for k, v in compat.iteritems(row._asdict())) - for row in self.itertuples(index=False)] + for k, v in compat.iteritems(row)) + for row in rows] elif orient.lower().startswith('i'): if not self.index.is_unique: raise ValueError( "DataFrame index must be unique for orient='index'." ) return into_c((t[0], dict(zip(self.columns, t[1:]))) - for t in self.itertuples()) + for t in self.itertuples(name=None)) else: raise ValueError("orient '{o}' not understood".format(o=orient)) diff --git a/pandas/tests/frame/test_convert_to.py b/pandas/tests/frame/test_convert_to.py index ddf85136126a1b..7b98395dd6dec1 100644 --- a/pandas/tests/frame/test_convert_to.py +++ b/pandas/tests/frame/test_convert_to.py @@ -488,3 +488,17 @@ def test_to_dict_index_dtypes(self, into, expected): result = DataFrame.from_dict(result, orient='index')[cols] expected = DataFrame.from_dict(expected, orient='index')[cols] tm.assert_frame_equal(result, expected) + + def test_to_dict_numeric_names(self): + # https://github.com/pandas-dev/pandas/issues/24940 + df = DataFrame({str(i): [i] for i in range(5)}) + result = set(df.to_dict('records')[0].keys()) + expected = set(df.columns) + assert result == expected + + def test_to_dict_wide(self): + # https://github.com/pandas-dev/pandas/issues/24939 + df = DataFrame({('A_{:d}'.format(i)): [i] for i in range(256)}) + result = df.to_dict('records')[0] + expected = {'A_{:d}'.format(i): i for i in range(256)} + assert result == expected