Repository: pandas-dev/pandas

Issue:
API: to_series/to_frame Index methods
xref https://github.com/pandas-dev/pandas/pull/15216#issuecomment-275240736

``Index.to_series()``
``MultiIndex.to_frame()``

should we harmonize? (e.g. make both available to both? for compat), leave it like this?

should also prob add the ``index=True`` kw to ``.to_series()`` for compat.


Discussion:
I don't see why we shouldn't harmonize API.  It makes it easier to use (obviously, the behavior will be different but at least the functions can be called).
@gfyoung feel like diving in on these? (we may need to deprecate some things).
@jreback : Just going through the backlog here and finally got to this.  For starters, `MultiIndex.to_series` already exists thanks to inheritance with `Index`.  Thus, I don't see why we wouldn't want to have `to_frame()` for consistency for `Index`.  Quite simple to implement IMO.

What do you think?

Resolving patch:
diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py
--- a/pandas/core/indexes/base.py
+++ b/pandas/core/indexes/base.py
@@ -1005,6 +1005,29 @@ def to_series(self, **kwargs):
                       index=self._shallow_copy(),
                       name=self.name)
 
+    def to_frame(self, index=True):
+        """
+        Create a DataFrame with a column containing the Index.
+
+        .. versionadded:: 0.21.0
+
+        Parameters
+        ----------
+        index : boolean, default True
+            Set the index of the returned DataFrame as the original Index.
+
+        Returns
+        -------
+        DataFrame : a DataFrame containing the original Index data.
+        """
+
+        from pandas import DataFrame
+        result = DataFrame(self._shallow_copy(), columns=[self.name or 0])
+
+        if index:
+            result.index = self
+        return result
+
     def _to_embed(self, keep_tz=False):
         """
         *this is an internal non-public method*
diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py
--- a/pandas/core/indexes/datetimes.py
+++ b/pandas/core/indexes/datetimes.py
@@ -915,6 +915,46 @@ def to_series(self, keep_tz=False):
                       index=self._shallow_copy(),
                       name=self.name)
 
+    def to_frame(self, index=True, keep_tz=False):
+        """
+        Create a DataFrame with a column containing the DatetimeIndex.
+
+        .. versionadded:: 0.21.0
+
+        Parameters
+        ----------
+        index : boolean, default True
+            Set the index of the returned DataFrame
+            as the original DatetimeIndex.
+
+        keep_tz : optional, defaults False.
+            return the data keeping the timezone.
+
+            If keep_tz is True:
+
+              If the timezone is not set, the resulting
+              Series will have a datetime64[ns] dtype.
+
+              Otherwise the DataFrame will have an datetime64[ns, tz] dtype;
+              the tz will be preserved.
+
+            If keep_tz is False:
+
+              DataFrame will have a datetime64[ns] dtype. TZ aware
+              objects will have the tz removed.
+
+        Returns
+        -------
+        DataFrame : a DataFrame containing the original DatetimeIndex data.
+        """
+
+        from pandas import DataFrame
+        result = DataFrame(self._to_embed(keep_tz), columns=[self.name or 0])
+
+        if index:
+            result.index = self
+        return result
+
     def _to_embed(self, keep_tz=False):
         """
         return an array repr of this object, potentially casting to object
diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py
--- a/pandas/core/indexes/multi.py
+++ b/pandas/core/indexes/multi.py
@@ -1010,18 +1010,18 @@ def _to_safe_for_reshape(self):
 
     def to_frame(self, index=True):
         """
-        Create a DataFrame with the columns the levels of the MultiIndex
+        Create a DataFrame with the levels of the MultiIndex as columns.
 
         .. versionadded:: 0.20.0
 
         Parameters
         ----------
         index : boolean, default True
-            return this MultiIndex as the index
+            Set the index of the returned DataFrame as the original MultiIndex.
 
         Returns
         -------
-        DataFrame
+        DataFrame : a DataFrame containing the original MultiIndex data.
         """
 
         from pandas import DataFrame


Test patch:
diff --git a/pandas/tests/indexes/common.py b/pandas/tests/indexes/common.py
--- a/pandas/tests/indexes/common.py
+++ b/pandas/tests/indexes/common.py
@@ -51,6 +51,21 @@ def test_to_series(self):
         assert s.index is not idx
         assert s.name == idx.name
 
+    def test_to_frame(self):
+        # see gh-15230
+        idx = self.create_index()
+        name = idx.name or 0
+
+        df = idx.to_frame()
+
+        assert df.index is idx
+        assert len(df.columns) == 1
+        assert df.columns[0] == name
+        assert df[name].values is not idx.values
+
+        df = idx.to_frame(index=False)
+        assert df.index is not idx
+
     def test_shift(self):
 
         # GH8083 test the base class for shift