Skip to content

Commit bda86c3

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: #28282
1 parent f9fb02e commit bda86c3

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

doc/source/whatsnew/v1.0.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ Other
983983
- Fixed ``pow`` operations for :class:`IntegerArray` when the other value is ``0`` or ``1`` (:issue:`29997`)
984984
- Bug in :meth:`Series.count` raises if use_inf_as_na is enabled (:issue:`29478`)
985985
- Bug in :class:`Index` where a non-hashable name could be set without raising ``TypeError`` (:issue:`29069`)
986-
986+
- Bug where :meth:`DataFrame.itertuples` would incorrectly determine whether or not namedtuples could be used for dataframes of 255 columns (:issue:`28282`)
987987

988988
.. _whatsnew_1000.contributors:
989989

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)