diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 7aa1c1e84aa09..e38b12757e37e 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -278,6 +278,7 @@ Other enhancements - :meth:`DatetimeIndex.astype` now supports casting timezone-naive indexes to ``datetime64[s]``, ``datetime64[ms]``, and ``datetime64[us]``, and timezone-aware indexes to the corresponding ``datetime64[unit, tzname]`` dtypes (:issue:`47579`) - :class:`Series` reducers (e.g. ``min``, ``max``, ``sum``, ``mean``) will now successfully operate when the dtype is numeric and ``numeric_only=True`` is provided; previously this would raise a ``NotImplementedError`` (:issue:`47500`) - :meth:`RangeIndex.union` now can return a :class:`RangeIndex` instead of a :class:`Int64Index` if the resulting values are equally spaced (:issue:`47557`, :issue:`43885`) +- :meth:`DataFrame.to_dict` now has a ``index`` parameter with default value True that can be set to False to exclude the index from the dictionary if orient is split or tight (:issue:`46398`) .. --------------------------------------------------------------------------- .. _whatsnew_150.notable_bug_fixes: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index ead4ea744c647..c63636299be92 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1811,7 +1811,7 @@ def to_numpy( return result - def to_dict(self, orient: str = "dict", into=dict): + def to_dict(self, orient: str = "dict", into=dict, index=True): """ Convert the DataFrame to a dictionary. @@ -1847,6 +1847,12 @@ def to_dict(self, orient: str = "dict", into=dict): instance of the mapping type you want. If you want a collections.defaultdict, you must pass it initialized. + index : bool, default True + When set to False, method returns a dict without an index key + (and index_names if using orient='tight'). + + .. versionadded:: 1.5.0 + Returns ------- dict, list or collections.abc.Mapping @@ -1958,36 +1964,66 @@ def to_dict(self, orient: str = "dict", into=dict): ) elif orient == "split": - return into_c( - ( - ("index", self.index.tolist()), - ("columns", self.columns.tolist()), + + if not index: + return into_c( ( - "data", - [ - list(map(maybe_box_native, t)) - for t in self.itertuples(index=False, name=None) - ], - ), + ("columns", self.columns.tolist()), + ( + "data", + [ + list(map(maybe_box_native, t)) + for t in self.itertuples(index=False, name=None) + ], + ), + ) + ) + else: + return into_c( + ( + ("index", self.index.tolist()), + ("columns", self.columns.tolist()), + ( + "data", + [ + list(map(maybe_box_native, t)) + for t in self.itertuples(index=False, name=None) + ], + ), + ) ) - ) elif orient == "tight": - return into_c( - ( - ("index", self.index.tolist()), - ("columns", self.columns.tolist()), + if not index: + return into_c( + ( + ("columns", self.columns.tolist()), + ( + "data", + [ + list(map(maybe_box_native, t)) + for t in self.itertuples(index=False, name=None) + ], + ), + ("column_names", list(self.columns.names)), + ) + ) + else: + return into_c( ( - "data", - [ - list(map(maybe_box_native, t)) - for t in self.itertuples(index=False, name=None) - ], - ), - ("index_names", list(self.index.names)), - ("column_names", list(self.columns.names)), + ("index", self.index.tolist()), + ("columns", self.columns.tolist()), + ( + "data", + [ + list(map(maybe_box_native, t)) + for t in self.itertuples(index=False, name=None) + ], + ), + ("index_names", list(self.index.names)), + ("column_names", list(self.columns.names)), + ) ) - ) elif orient == "series": return into_c((k, v) for k, v in self.items()) diff --git a/pandas/tests/frame/methods/test_to_dict.py b/pandas/tests/frame/methods/test_to_dict.py index 6d5c32cae7368..b3a39c720fc4e 100644 --- a/pandas/tests/frame/methods/test_to_dict.py +++ b/pandas/tests/frame/methods/test_to_dict.py @@ -421,3 +421,24 @@ def test_to_dict_returns_native_types(self, orient, data, expected_types): for i, key, value in assertion_iterator: assert value == data[key][i] assert type(value) is expected_types[key][i] + + def test_to_dict_index_orient_split(self): + # GH#46398 + df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["row1", "row2", "row3"]) + result = df.to_dict(orient="split", index=False) + expected = { + "columns": ["A", "B"], + "data": [[1, 4], [2, 5], [3, 6]], + } + tm.assert_dict_equal(result, expected) + + def test_to_dict_index_orient_tight(self): + # GH#46398 + df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["row1", "row2", "row3"]) + result = df.to_dict(orient="tight", index=False) + expected = { + "columns": ["A", "B"], + "data": [[1, 4], [2, 5], [3, 6]], + "column_names": [None], + } + tm.assert_dict_equal(result, expected)