Skip to content

Commit e4b035e

Browse files
committed
BUG: Ensure df.itertuples() uses plain tuples correctly
Currently DataFrame.itertuples() has an off by one error when it inspects whether or not it should return namedtuples or plain tuples in it's response. This PR addresses that bug by correcting the condition that is used when making the check. Closes: pandas-dev#28282
1 parent 641051f commit e4b035e

File tree

3 files changed

+19
-2
lines changed

3 files changed

+19
-2
lines changed

doc/source/whatsnew/v1.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ Other
987987
- Bug in :class:`Index` where a non-hashable name could be set without raising ``TypeError`` (:issue:`29069`)
988988
- Bug in :class:`DataFrame` constructor when passing a 2D ``ndarray`` and an extension dtype (:issue:`12513`)
989989
- Bug in :meth:`DaataFrame.to_csv` when supplied a series with a ``dtype="string"`` and a ``na_rep``, the ``na_rep`` was being truncated to 2 characters. (:issue:`29975`)
990+
- Bug where :meth:`DataFrame.itertuples` would incorrectly determine whether or not namedtuples could be used for dataframes of 255 columns (:issue:`28282`)
990991

991992
.. _whatsnew_1000.contributors:
992993

pandas/core/frame.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,8 +1018,8 @@ def itertuples(self, index=True, name="Pandas"):
10181018
# use integer indexing because of possible duplicate column names
10191019
arrays.extend(self.iloc[:, k] for k in range(len(self.columns)))
10201020

1021-
# Python 3 supports at most 255 arguments to constructor
1022-
if name is not None and len(self.columns) + index < 256:
1021+
# Python versions before 3.7 support at most 255 arguments to constructor
1022+
if name is not None and len(self.columns) + index < 255:
10231023
itertuple = collections.namedtuple(name, fields, rename=True)
10241024
return map(itertuple._make, zip(*arrays))
10251025

pandas/tests/frame/test_api.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,22 @@ def test_sequence_like_with_categorical(self):
288288
for c, col in df.items():
289289
str(s)
290290

291+
def test_itertuples_fallback_to_regular_tuples(self):
292+
# GH 28282
293+
294+
df_254_columns = DataFrame([{f"foo_{i}": f"bar_{i}" for i in range(254)}])
295+
result_254_columns = next(df_254_columns.itertuples(index=False))
296+
assert isinstance(result_254_columns, tuple)
297+
assert result_254_columns.foo_1 == "bar_1"
298+
299+
df_255_columns = DataFrame([{f"foo_{i}": f"bar_{i}" for i in range(255)}])
300+
result_255_columns = next(df_255_columns.itertuples(index=False))
301+
assert isinstance(result_255_columns, tuple)
302+
303+
# Dataframes with >=255 columns will fallback to regular tuples
304+
with pytest.raises(AttributeError):
305+
result_255_columns.foo_1
306+
291307
def test_len(self, float_frame):
292308
assert len(float_frame) == len(float_frame.index)
293309

0 commit comments

Comments
 (0)