From 77c571b507af31a6c32e856d59f99f52f97259f3 Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Tue, 25 Feb 2020 18:59:45 +0000 Subject: [PATCH 1/5] first draft --- pandas/core/frame.py | 7 ++++++- pandas/core/indexes/timedeltas.py | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 7efb4fbb878d6..be0ffbf046001 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1027,7 +1027,11 @@ def itertuples(self, index=True, name="Pandas"): fields.insert(0, "Index") # use integer indexing because of possible duplicate column names - arrays.extend(self.iloc[:, k] for k in range(len(self.columns))) + if len(self.columns) > 0: + arrays.extend(self.iloc[:, k] for k in range(len(self.columns))) + else: + arrays.extend([() for _ in range(len(self))]) + return iter(arrays) # Python versions before 3.7 support at most 255 arguments to constructors can_return_named_tuples = PY37 or len(self.columns) + index < 255 @@ -1407,6 +1411,7 @@ def to_dict(self, orient="dict", into=dict): elif orient.lower().startswith("l"): return into_c((k, v.tolist()) for k, v in self.items()) elif orient.lower().startswith("sp"): + breakpoint() return into_c( ( ("index", self.index.tolist()), diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index b3b2bc46f6659..a36648373bd71 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -349,6 +349,9 @@ def timedelta_range( '5 days 00:00:00'], dtype='timedelta64[ns]', freq=None) """ + if start is not None and end is not None and freq is not None: + raise ValueError("ambiguous") + if freq is None and com.any_none(periods, start, end): freq = "D" From 02ef338faa1aec1478c457522967569b0499245e Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Tue, 25 Feb 2020 19:21:39 +0000 Subject: [PATCH 2/5] add tests --- pandas/core/frame.py | 1 - pandas/tests/frame/methods/test_to_dict.py | 7 +++++++ pandas/tests/frame/test_api.py | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index be0ffbf046001..ed49f750d2061 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1411,7 +1411,6 @@ def to_dict(self, orient="dict", into=dict): elif orient.lower().startswith("l"): return into_c((k, v.tolist()) for k, v in self.items()) elif orient.lower().startswith("sp"): - breakpoint() return into_c( ( ("index", self.index.tolist()), diff --git a/pandas/tests/frame/methods/test_to_dict.py b/pandas/tests/frame/methods/test_to_dict.py index cd9bd169322fd..0780a9ea30a40 100644 --- a/pandas/tests/frame/methods/test_to_dict.py +++ b/pandas/tests/frame/methods/test_to_dict.py @@ -262,3 +262,10 @@ def test_to_dict_orient_dtype(self): "c": type(df_dict["c"]), } assert result == expected + + def test_to_dict_no_rows_split(self): + # GH 25408 + columns = ["A", "B"] + result = DataFrame(columns=columns).transpose().to_dict(orient="split") + expected = {'index': ['A', 'B'], 'columns': [], 'data': [[], []]} + assert result == expected diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index a021dd91a7d26..72819e04e6846 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -285,6 +285,12 @@ def test_itertuples(self, float_frame): assert hasattr(result_255_columns, "_fields") else: assert not hasattr(result_255_columns, "_fields") + + # GH 25408 + df_0_columns = DataFrame(index=['A', 'B']) + result = list(df_0_columns.itertuples()) + tm.assert_index_equal(result[0], pd.Index(['A', 'B'])) + assert result[1:] == [(), ()] def test_sequence_like_with_categorical(self): From d74ac7e4f40492001ad54d8fa979732f3110d6e5 Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Tue, 25 Feb 2020 19:22:20 +0000 Subject: [PATCH 3/5] lint --- pandas/tests/frame/methods/test_to_dict.py | 2 +- pandas/tests/frame/test_api.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/tests/frame/methods/test_to_dict.py b/pandas/tests/frame/methods/test_to_dict.py index 0780a9ea30a40..a934dffa763fd 100644 --- a/pandas/tests/frame/methods/test_to_dict.py +++ b/pandas/tests/frame/methods/test_to_dict.py @@ -267,5 +267,5 @@ def test_to_dict_no_rows_split(self): # GH 25408 columns = ["A", "B"] result = DataFrame(columns=columns).transpose().to_dict(orient="split") - expected = {'index': ['A', 'B'], 'columns': [], 'data': [[], []]} + expected = {"index": ["A", "B"], "columns": [], "data": [[], []]} assert result == expected diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index 72819e04e6846..bf52e54695a15 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -285,11 +285,11 @@ def test_itertuples(self, float_frame): assert hasattr(result_255_columns, "_fields") else: assert not hasattr(result_255_columns, "_fields") - + # GH 25408 - df_0_columns = DataFrame(index=['A', 'B']) + df_0_columns = DataFrame(index=["A", "B"]) result = list(df_0_columns.itertuples()) - tm.assert_index_equal(result[0], pd.Index(['A', 'B'])) + tm.assert_index_equal(result[0], pd.Index(["A", "B"])) assert result[1:] == [(), ()] def test_sequence_like_with_categorical(self): From 6cd559c9ef13c1adb03ac19b81207ffb268104b4 Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Tue, 25 Feb 2020 21:57:29 +0000 Subject: [PATCH 4/5] whatsnew --- doc/source/whatsnew/v1.1.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 705c335acfb48..b010b71abab3f 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -249,6 +249,7 @@ Other instead of ``TypeError: Can only append a Series if ignore_index=True or if the Series has a name`` (:issue:`30871`) - Set operations on an object-dtype :class:`Index` now always return object-dtype results (:issue:`31401`) - Bug in :meth:`AbstractHolidayCalendar.holidays` when no rules were defined (:issue:`31415`) +- Bug in :meth:`DataFrame.itertuples` was returning empty list when DataFrame has no columns (:issue:`25408`) - .. --------------------------------------------------------------------------- From b467b6c60daaf6ea5bf821ed52056e9b96e27256 Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Tue, 25 Feb 2020 21:59:48 +0000 Subject: [PATCH 5/5] revert --- pandas/core/indexes/timedeltas.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index a36648373bd71..b3b2bc46f6659 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -349,9 +349,6 @@ def timedelta_range( '5 days 00:00:00'], dtype='timedelta64[ns]', freq=None) """ - if start is not None and end is not None and freq is not None: - raise ValueError("ambiguous") - if freq is None and com.any_none(periods, start, end): freq = "D"