Repository: databricks/koalas

Issue:
Fix the index of `Index.to_series()`.
The index of `Index.to_series()` doesn't address the change of the index itself.

E.g.,

```py
>>> pidx
Int64Index([1, 2, 3], dtype='int64')
>>> (pidx + 1).to_series()
2    2
3    3
4    4
dtype: int64
```

whereas

```py
>>> kidx
Int64Index([1, 2, 3], dtype='int64')
>>> (kidx + 1).to_series()
1    2
2    3
3    4
Name: 0, dtype: int64
```


Discussion:
I'll take it.

Resolving patch:
diff --git a/databricks/koalas/indexes.py b/databricks/koalas/indexes.py
--- a/databricks/koalas/indexes.py
+++ b/databricks/koalas/indexes.py
@@ -99,26 +99,16 @@ class Index(IndexOpsMixin):
     Index(['a', 'b', 'c'], dtype='object')
     """
 
-    def __init__(
-        self,
-        data: Union[DataFrame, list],
-        dtype=None,
-        name=None,
-        scol: Optional[spark.Column] = None,
-    ) -> None:
+    def __init__(self, data: Union[DataFrame, list], dtype=None, name=None) -> None:
         if isinstance(data, DataFrame):
             assert dtype is None
             assert name is None
             kdf = data
         else:
-            assert scol is None
             kdf = DataFrame(index=pd.Index(data=data, dtype=dtype, name=name))
-        if scol is None:
-            scol = kdf._internal.index_spark_columns[0]
         internal = kdf._internal.copy(
-            spark_column=scol,
+            spark_column=kdf._internal.index_spark_columns[0],
             column_labels=kdf._internal.index_names,
-            data_spark_columns=kdf._internal.index_spark_columns,
             column_label_names=None,
         )
         IndexOpsMixin.__init__(self, internal, kdf)
@@ -130,7 +120,11 @@ def _with_new_scol(self, scol: spark.Column) -> "Index":
         :param scol: the new Spark Column
         :return: the copied Index
         """
-        return Index(self._kdf, scol=scol)
+        sdf = self._internal.spark_frame.select(scol)
+        internal = _InternalFrame(
+            spark_frame=sdf, index_map=OrderedDict(zip(sdf.columns, self._internal.index_names))
+        )
+        return DataFrame(internal).index
 
     # This method is used via `DataFrame.info` API internally.
     def _summary(self, name=None):
@@ -360,15 +354,7 @@ def to_pandas(self) -> pd.Index:
         >>> df['dogs'].index.to_pandas()
         Index(['a', 'b', 'c', 'd'], dtype='object')
         """
-        sdf = self._kdf._sdf.select(self._scol)
-        internal = self._kdf._internal.copy(
-            spark_frame=sdf,
-            index_map=OrderedDict({sdf.schema[0].name: self._kdf._internal.index_names[0]}),
-            column_labels=[],
-            data_spark_columns=[],
-            column_label_names=None,
-        )
-        return DataFrame(internal)._to_internal_pandas().index
+        return self._internal.to_pandas_frame.index
 
     toPandas = to_pandas
 
@@ -639,8 +625,8 @@ def drop_duplicates(self):
 
         >>> idx = ks.Index(['lama', 'cow', 'lama', 'beetle', 'lama', 'hippo'])
 
-        >>> idx.drop_duplicates() # doctest: +SKIP
-        Index(['lama', 'cow', 'beetle', 'hippo'], dtype='object')
+        >>> idx.drop_duplicates().sort_values()
+        Index(['beetle', 'cow', 'hippo', 'lama'], dtype='object')
         """
         sdf = self._internal.spark_frame.select(
             self._internal.index_spark_columns
@@ -890,8 +876,7 @@ def dropna(self):
         kdf = self._kdf.copy()
         sdf = kdf._internal.spark_frame.select(self._internal.index_spark_columns).dropna()
         internal = _InternalFrame(spark_frame=sdf, index_map=self._internal.index_map)
-        kdf = DataFrame(internal)
-        return Index(kdf) if type(self) == Index else MultiIndex(kdf)
+        return DataFrame(internal).index
 
     def unique(self, level=None):
         """
@@ -998,8 +983,7 @@ def copy(self, name=None):
         >>> df.index.copy(name='snake')
         Index(['cobra', 'viper', 'sidewinder'], dtype='object', name='snake')
         """
-        internal = self._kdf._internal.copy()
-        result = Index(ks.DataFrame(internal), scol=self._scol)
+        result = Index(self._kdf.copy())
         if name:
             result.name = name
         return result
@@ -1512,9 +1496,9 @@ def is_all_dates(self):
 
     def repeat(self, repeats: int) -> "Index":
         """
-        Repeat elements of a Index.
+        Repeat elements of a Index/MultiIndex.
 
-        Returns a new Index where each element of the current Index
+        Returns a new Index/MultiIndex where each element of the current Index/MultiIndex
         is repeated consecutively a given number of times.
 
         Parameters
@@ -1526,13 +1510,12 @@ def repeat(self, repeats: int) -> "Index":
 
         Returns
         -------
-        repeated_index : Index
-            Newly created Index with repeated elements.
+        repeated_index : Index/MultiIndex
+            Newly created Index/MultiIndex with repeated elements.
 
         See Also
         --------
         Series.repeat : Equivalent function for Series.
-        MultiIndex.repeat : Equivalent function for MultiIndex.
 
         Examples
         --------
@@ -1541,15 +1524,34 @@ def repeat(self, repeats: int) -> "Index":
         Index(['a', 'b', 'c'], dtype='object')
         >>> idx.repeat(2)
         Index(['a', 'b', 'c', 'a', 'b', 'c'], dtype='object')
+
+        For MultiIndex,
+
+        >>> midx = ks.MultiIndex.from_tuples([('x', 'a'), ('x', 'b'), ('y', 'c')])
+        >>> midx  # doctest: +SKIP
+        MultiIndex([('x', 'a'),
+                    ('x', 'b'),
+                    ('y', 'c')],
+                   )
+        >>> midx.repeat(2)  # doctest: +SKIP
+        MultiIndex([('x', 'a'),
+                    ('x', 'b'),
+                    ('y', 'c'),
+                    ('x', 'a'),
+                    ('x', 'b'),
+                    ('y', 'c')],
+                   )
+        >>> midx.repeat(0)  # doctest: +SKIP
+        MultiIndex([], )
         """
         if not isinstance(repeats, int):
             raise ValueError("`repeats` argument must be integer, but got {}".format(type(repeats)))
         elif repeats < 0:
             raise ValueError("negative dimensions are not allowed")
 
-        sdf = self._internal.spark_frame.select(self._internal.spark_column)
+        sdf = self._internal.spark_frame.select(self._internal.index_spark_columns)
         internal = _InternalFrame(
-            spark_frame=sdf, index_map=OrderedDict({sdf.columns[0]: self._internal.index_names[0]})
+            spark_frame=sdf, index_map=OrderedDict(zip(sdf.columns, self._internal.index_names))
         )
         kdf = DataFrame(internal)  # type: DataFrame
         if repeats == 0:
@@ -2040,9 +2042,7 @@ def copy(self):
         """
         Make a copy of this object.
         """
-        internal = self._kdf._internal.copy()
-        result = MultiIndex(ks.DataFrame(internal))
-        return result
+        return MultiIndex(self._kdf.copy())
 
     def symmetric_difference(self, other, result_name=None, sort=None):
         """
@@ -2219,64 +2219,6 @@ def is_all_dates(self):
         """
         return False
 
-    def repeat(self, repeats: int) -> "MultiIndex":
-        """
-        Repeat elements of a MultiIndex.
-
-        Returns a new MultiIndex where each element of the current MultiIndex
-        is repeated consecutively a given number of times.
-
-        Parameters
-        ----------
-        repeats : int
-            The number of repetitions for each element. This should be a
-            non-negative integer. Repeating 0 times will return an empty
-            Index.
-
-        Returns
-        -------
-        repeated_index : MultiIndex
-            Newly created MultiIndex with repeated elements.
-
-        See Also
-        --------
-        Series.repeat : Equivalent function for Series.
-        Index.repeat : Equivalent function for Index.
-
-        Examples
-        --------
-        >>> midx = ks.MultiIndex.from_tuples([('x', 'a'), ('x', 'b'), ('y', 'c')])
-        >>> midx  # doctest: +SKIP
-        MultiIndex([('x', 'a'),
-                    ('x', 'b'),
-                    ('y', 'c')],
-                   )
-        >>> midx.repeat(2)  # doctest: +SKIP
-        MultiIndex([('x', 'a'),
-                    ('x', 'b'),
-                    ('y', 'c'),
-                    ('x', 'a'),
-                    ('x', 'b'),
-                    ('y', 'c')],
-                   )
-        >>> midx.repeat(0)  # doctest: +SKIP
-        MultiIndex([], )
-        """
-        if not isinstance(repeats, int):
-            raise ValueError("`repeats` argument must be integer, but got {}".format(type(repeats)))
-        elif repeats < 0:
-            raise ValueError("negative dimensions are not allowed")
-
-        sdf = self._internal.spark_frame.select(self._internal.index_spark_columns)
-        internal = _InternalFrame(
-            spark_frame=sdf, index_map=OrderedDict(zip(sdf.columns, self._internal.index_names))
-        )
-        kdf = DataFrame(internal)  # type: DataFrame
-        if repeats == 0:
-            return DataFrame(kdf._internal.with_filter(F.lit(False))).index
-        else:
-            return ks.concat([kdf] * repeats).index
-
     def __getattr__(self, item: str) -> Any:
         if hasattr(_MissingPandasLikeMultiIndex, item):
             property_or_func = getattr(_MissingPandasLikeMultiIndex, item)
diff --git a/databricks/koalas/indexing.py b/databricks/koalas/indexing.py
--- a/databricks/koalas/indexing.py
+++ b/databricks/koalas/indexing.py
@@ -801,7 +801,6 @@ class iLocIndexer(_LocIndexerLike):
     - A boolean array for column selection.
     - A slice object with ints for column selection, e.g. ``1:7``.
     - A slice object with ints without start and step for row selection, e.g. ``:7``.
-    - A conditional boolean Index for row selection.
 
     Not allowed inputs which pandas allows are:
 
@@ -862,13 +861,6 @@ class iLocIndexer(_LocIndexerLike):
     1   100   200   300   400
     2  1000  2000  3000  4000
 
-    Conditional that returns a boolean Series
-
-    >>> df.iloc[df.index % 2 == 0]
-          a     b     c     d
-    0     1     2     3     4
-    2  1000  2000  3000  4000
-
     **Indexing both axes**
 
     You can mix the indexer types for the index and columns. Use ``:`` to
diff --git a/databricks/koalas/series.py b/databricks/koalas/series.py
--- a/databricks/koalas/series.py
+++ b/databricks/koalas/series.py
@@ -4357,7 +4357,6 @@ def repeat(self, repeats: int) -> "Series":
         See Also
         --------
         Index.repeat : Equivalent function for Index.
-        MultiIndex.repeat : Equivalent function for MultiIndex.
 
         Examples
         --------


Test patch:
diff --git a/databricks/koalas/tests/test_indexes.py b/databricks/koalas/tests/test_indexes.py
--- a/databricks/koalas/tests/test_indexes.py
+++ b/databricks/koalas/tests/test_indexes.py
@@ -77,8 +77,7 @@ def test_to_series(self):
         self.assert_eq(kidx.to_series(), pidx.to_series())
         self.assert_eq(kidx.to_series(name="a"), pidx.to_series(name="a"))
 
-        # FIXME: the index values are not addressed the change. (#1190)
-        # self.assert_eq((kidx + 1).to_series(), (pidx + 1).to_series())
+        self.assert_eq((kidx + 1).to_series(), (pidx + 1).to_series())
 
         pidx = self.pdf.set_index("b", append=True).index
         kidx = self.kdf.set_index("b", append=True).index
@@ -263,7 +262,53 @@ def test_multi_index_copy(self):
 
         self.assert_eq(kdf.index.copy(), pdf.index.copy())
 
+    def test_drop_duplicates(self):
+        pidx = pd.Index([4, 2, 4, 1, 4, 3])
+        kidx = ks.from_pandas(pidx)
+
+        self.assert_eq(kidx.drop_duplicates().sort_values(), pidx.drop_duplicates().sort_values())
+        self.assert_eq(
+            (kidx + 1).drop_duplicates().sort_values(), (pidx + 1).drop_duplicates().sort_values()
+        )
+
+    def test_dropna(self):
+        pidx = pd.Index([np.nan, 2, 4, 1, np.nan, 3])
+        kidx = ks.from_pandas(pidx)
+
+        self.assert_eq(kidx.dropna(), pidx.dropna())
+        self.assert_eq((kidx + 1).dropna(), (pidx + 1).dropna())
+
     def test_index_symmetric_difference(self):
+        pidx1 = pd.Index([1, 2, 3, 4])
+        pidx2 = pd.Index([2, 3, 4, 5])
+        kidx1 = ks.from_pandas(pidx1)
+        kidx2 = ks.from_pandas(pidx2)
+
+        self.assert_eq(
+            kidx1.symmetric_difference(kidx2).sort_values(),
+            pidx1.symmetric_difference(pidx2).sort_values(),
+        )
+        self.assert_eq(
+            (kidx1 + 1).symmetric_difference(kidx2).sort_values(),
+            (pidx1 + 1).symmetric_difference(pidx2).sort_values(),
+        )
+
+        pmidx1 = pd.MultiIndex(
+            [["lama", "cow", "falcon"], ["speed", "weight", "length"]],
+            [[0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 0, 0, 0, 1, 2, 0, 1, 2]],
+        )
+        pmidx2 = pd.MultiIndex(
+            [["koalas", "cow", "falcon"], ["speed", "weight", "length"]],
+            [[0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 0, 0, 0, 1, 2, 0, 1, 2]],
+        )
+        kmidx1 = ks.from_pandas(pmidx1)
+        kmidx2 = ks.from_pandas(pmidx2)
+
+        self.assert_eq(
+            kmidx1.symmetric_difference(kmidx2).sort_values(),
+            pmidx1.symmetric_difference(pmidx2).sort_values(),
+        )
+
         idx = ks.Index(["a", "b", "c"])
         midx = ks.MultiIndex.from_tuples([("a", "x"), ("b", "y"), ("c", "z")])
 
@@ -894,6 +939,7 @@ def test_repeat(self):
 
         self.assert_eq(kidx.repeat(3).sort_values(), pidx.repeat(3).sort_values())
         self.assert_eq(kidx.repeat(0).sort_values(), pidx.repeat(0).sort_values())
+        self.assert_eq((kidx + "x").repeat(3).sort_values(), (pidx + "x").repeat(3).sort_values())
 
         self.assertRaises(ValueError, lambda: kidx.repeat(-1))
         self.assertRaises(ValueError, lambda: kidx.repeat("abc"))
diff --git a/databricks/koalas/tests/test_indexing.py b/databricks/koalas/tests/test_indexing.py
--- a/databricks/koalas/tests/test_indexing.py
+++ b/databricks/koalas/tests/test_indexing.py
@@ -650,7 +650,7 @@ def test_iloc(self):
             self.assert_eq(kdf.iloc[:, indexer], pdf.iloc[:, indexer])
             self.assert_eq(kdf.iloc[:1, indexer], pdf.iloc[:1, indexer])
             self.assert_eq(kdf.iloc[:-1, indexer], pdf.iloc[:-1, indexer])
-            self.assert_eq(kdf.iloc[kdf.index == 2, indexer], pdf.iloc[pdf.index == 2, indexer])
+            # self.assert_eq(kdf.iloc[kdf.index == 2, indexer], pdf.iloc[pdf.index == 2, indexer])
 
     def test_iloc_multiindex_columns(self):
         arrays = [np.array(["bar", "bar", "baz", "baz"]), np.array(["one", "two", "one", "two"])]
@@ -662,7 +662,8 @@ def test_iloc_multiindex_columns(self):
             self.assert_eq(kdf.iloc[:, indexer], pdf.iloc[:, indexer])
             self.assert_eq(kdf.iloc[:1, indexer], pdf.iloc[:1, indexer])
             self.assert_eq(kdf.iloc[:-1, indexer], pdf.iloc[:-1, indexer])
-            self.assert_eq(kdf.iloc[kdf.index == "B", indexer], pdf.iloc[pdf.index == "B", indexer])
+            # self.assert_eq(kdf.iloc[kdf.index == "B", indexer],
+            #                pdf.iloc[pdf.index == "B", indexer])
 
     def test_iloc_series(self):
         pseries = pd.Series([1, 2, 3])