Skip to content

Commit 730b22f

Browse files
committed
Address comments.
1. Ensure we return named tuples in more cases (when using python >= 3.7) 2. Move test around to be with the itertuples test 3. Update docstring with the new behaviour.
1 parent bda86c3 commit 730b22f

File tree

2 files changed

+26
-19
lines changed

2 files changed

+26
-19
lines changed

pandas/core/frame.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
from pandas._libs import algos as libalgos, lib
4040
from pandas._typing import Axes, Dtype, FilePathOrBuffer
41+
from pandas.compat import PY37
4142
from pandas.compat._optional import import_optional_dependency
4243
from pandas.compat.numpy import function as nv
4344
from pandas.util._decorators import (
@@ -975,7 +976,8 @@ def itertuples(self, index=True, name="Pandas"):
975976
-----
976977
The column names will be renamed to positional names if they are
977978
invalid Python identifiers, repeated, or start with an underscore.
978-
With a large number of columns (>255), regular tuples are returned.
979+
On python versions < 3.7 regular tuples are returned for DataFrames
980+
with a large number of columns (>254).
979981
980982
Examples
981983
--------
@@ -1018,8 +1020,9 @@ def itertuples(self, index=True, name="Pandas"):
10181020
# use integer indexing because of possible duplicate column names
10191021
arrays.extend(self.iloc[:, k] for k in range(len(self.columns)))
10201022

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:
1023+
# Python versions before 3.7 support at most 255 arguments to constructors
1024+
can_return_named_tuples = PY37 or len(self.columns) + index < 255
1025+
if name is not None and can_return_named_tuples:
10231026
itertuple = collections.namedtuple(name, fields, rename=True)
10241027
return map(itertuple._make, zip(*arrays))
10251028

pandas/tests/frame/test_api.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import pandas as pd
99
from pandas import Categorical, DataFrame, Series, compat, date_range, timedelta_range
10+
from pandas.compat import PY37
1011
import pandas.util.testing as tm
1112

1213

@@ -264,6 +265,25 @@ def test_itertuples(self, float_frame):
264265
assert not hasattr(tup3, "_fields")
265266
assert isinstance(tup3, tuple)
266267

268+
def test_itertuples_fallback_to_regular_tuples(self):
269+
# GH 28282
270+
271+
df_254_columns = DataFrame([{f"foo_{i}": f"bar_{i}" for i in range(254)}])
272+
result_254_columns = next(df_254_columns.itertuples(index=False))
273+
assert isinstance(result_254_columns, tuple)
274+
assert result_254_columns.foo_1 == "bar_1"
275+
276+
df_255_columns = DataFrame([{f"foo_{i}": f"bar_{i}" for i in range(255)}])
277+
result_255_columns = next(df_255_columns.itertuples(index=False))
278+
assert isinstance(result_255_columns, tuple)
279+
280+
# Dataframes with >=255 columns will fallback to regular tuples on python < 3.7
281+
if not PY37:
282+
with pytest.raises(AttributeError):
283+
result_255_columns.foo_1
284+
else:
285+
assert result_254_columns.foo_1 == "bar_1"
286+
267287
def test_sequence_like_with_categorical(self):
268288

269289
# GH 7839
@@ -288,22 +308,6 @@ def test_sequence_like_with_categorical(self):
288308
for c, col in df.items():
289309
str(s)
290310

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-
307311
def test_len(self, float_frame):
308312
assert len(float_frame) == len(float_frame.index)
309313

0 commit comments

Comments
 (0)