Repository: modin-project/modin

Issue:
df.describe() error in modin ubuntu
### 🤖 This is a bot message 🤖 

bug_reports@modin.org has been sent an email reporting the following bug:

### Begin Report
```
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
~/.local/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj)
    700                 type_pprinters=self.type_printers,
    701                 deferred_pprinters=self.deferred_printers)
--> 702             printer.pretty(obj)
    703             printer.flush()
    704             return stream.getvalue()

~/.local/lib/python3.6/site-packages/IPython/lib/pretty.py in pretty(self, obj)
    400                         if cls is not object \
    401                                 and callable(cls.__dict__.get('__repr__')):
--> 402                             return _repr_pprint(obj, self, cycle)
    403 
    404             return _default_pprint(obj, self, cycle)

~/.local/lib/python3.6/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
    695     """A pprint that just redirects to the normal repr function."""
    696     # Find newlines and replace them with p.break_()
--> 697     output = repr(obj)
    698     for idx,output_line in enumerate(output.splitlines()):
    699         if idx:

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/pandas/dataframe.py in __repr__(self)
    136         num_cols = 30
    137 
--> 138         result = repr(self._build_repr_df(num_rows, num_cols))
    139         if len(self.index) > num_rows or len(self.columns) > num_cols:
    140             # The split here is so that we don't repr pandas row lengths.

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/pandas/dataframe.py in _build_repr_df(self, num_rows, num_cols)
    107 
    108         if len(self.columns) <= num_cols:
--> 109             head_front = head.to_pandas()
    110             # Creating these empty to make the concat logic simpler
    111             head_back = pandas.DataFrame()

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/data_management/query_compiler/pandas_query_compiler.py in to_pandas(self)
    480         else:
    481             ErrorMessage.catch_bugs_and_request_email(
--> 482                 len(df.index) != len(self.index) or len(df.columns) != len(self.columns)
    483             )
    484             df.index = self.index

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/error_message.py in catch_bugs_and_request_email(cls, failure_condition)
     36         if failure_condition:
     37             raise Exception(
---> 38                 "Internal Error. "
     39                 "Please email bug_reports@modin.org with the traceback and command that"
     40                 " caused this error."

Exception: Internal Error. Please email bug_reports@modin.org with the traceback and command that caused this error.

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
~/.local/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj)
    343             method = get_real_method(obj, self.print_method)
    344             if method is not None:
--> 345                 return method()
    346             return None
    347         else:

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/pandas/dataframe.py in _repr_html_(self)
    158         # We use pandas _repr_html_ to get a string of the HTML representation
    159         # of the dataframe.
--> 160         result = self._build_repr_df(num_rows, num_cols)._repr_html_()
    161         if len(self.index) > num_rows or len(self.columns) > num_cols:
    162             # We split so that we insert our correct dataframe dimensions.

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/pandas/dataframe.py in _build_repr_df(self, num_rows, num_cols)
    107 
    108         if len(self.columns) <= num_cols:
--> 109             head_front = head.to_pandas()
    110             # Creating these empty to make the concat logic simpler
    111             head_back = pandas.DataFrame()

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/data_management/query_compiler/pandas_query_compiler.py in to_pandas(self)
    480         else:
    481             ErrorMessage.catch_bugs_and_request_email(
--> 482                 len(df.index) != len(self.index) or len(df.columns) != len(self.columns)
    483             )
    484             df.index = self.index

~/.conda/envs/deepdream/lib/python3.6/site-packages/modin/error_message.py in catch_bugs_and_request_email(cls, failure_condition)
     36         if failure_condition:
     37             raise Exception(
---> 38                 "Internal Error. "
     39                 "Please email bug_reports@modin.org with the traceback and command that"
     40                 " caused this error."

Exception: Internal Error. Please email bug_reports@modin.org with the traceback and command that caused this err
```

### Developer notes:
Can reproduce with the following code (dtypes are important here):
```python
import modin.pandas as pd 
df = pd.DataFrame({"col1": list("abc"), "col2": list("abc"), "col3": list("abc"), "col4": [1,2,3]})
print(df.describe())
print(df.describe().columns)
```
In this case, the `string` columns are not properly filtered out of the final columns.


Discussion:

Resolving patch:
diff --git a/modin/backends/pandas/query_compiler.py b/modin/backends/pandas/query_compiler.py
--- a/modin/backends/pandas/query_compiler.py
+++ b/modin/backends/pandas/query_compiler.py
@@ -1693,48 +1693,13 @@ def describe(self, **kwargs):
         Returns:
             DataFrame object containing the descriptive statistics of the DataFrame.
         """
-        # Only describe numeric if there are numeric columns
-        # Otherwise, describe all
-        new_columns = self.numeric_columns(include_bool=False)
-        include = kwargs.get("include", None)
-        if len(new_columns) != 0 and include is not None:
-            if not isinstance(include, np.dtype) and include == "all":
-                new_columns = self.columns
-            else:
-                new_columns = self.dtypes[
-                    [
-                        any(
-                            (isinstance(inc, np.dtype) and inc == d)
-                            or (
-                                not isinstance(inc, np.dtype)
-                                and inc.__subclasscheck__(getattr(np, d.__str__()))
-                            )
-                            for inc in include
-                        )
-                        for d in self.dtypes.values
-                    ]
-                ].index
-        elif len(new_columns) == 0:
-            new_columns = [
-                self.columns[i]
-                for i in range(len(self.columns))
-                if self.dtypes[i] != np.dtype("datetime64[ns]")
-            ]
-        else:
-            exclude = kwargs.get("exclude", None)
-            # This is done to check against the default dtypes with 'in'.
-            # We don't change `include` in kwargs, so we can just use this for the
-            # check.
-            include = []
-            default_excludes = [np.timedelta64, np.datetime64, np.object, np.bool]
-            add_to_excludes = [e for e in default_excludes if e not in include]
-            if isinstance(exclude, list):
-                exclude.extend(add_to_excludes)
-            else:
-                exclude = add_to_excludes
-            kwargs["exclude"] = exclude
-            # Update `new_columns` to reflect the included types
-            new_columns = self.dtypes[~self.dtypes.isin(exclude)].index
+        # Use pandas to calculate the correct columns
+        new_columns = (
+            pandas.DataFrame(columns=self.columns)
+            .astype(self.dtypes)
+            .describe(**kwargs)
+            .columns
+        )
 
         def describe_builder(df, internal_indices=[], **kwargs):
             return df.iloc[:, internal_indices].describe(**kwargs)


Test patch:
diff --git a/modin/pandas/test/test_dataframe.py b/modin/pandas/test/test_dataframe.py
--- a/modin/pandas/test/test_dataframe.py
+++ b/modin/pandas/test/test_dataframe.py
@@ -1509,6 +1509,30 @@ def test_describe(data):
         )
 
 
+def test_describe_dtypes():
+    modin_df = pd.DataFrame(
+        {
+            "col1": list("abc"),
+            "col2": list("abc"),
+            "col3": list("abc"),
+            "col4": [1, 2, 3],
+        }
+    )
+    pandas_df = pandas.DataFrame(
+        {
+            "col1": list("abc"),
+            "col2": list("abc"),
+            "col3": list("abc"),
+            "col4": [1, 2, 3],
+        }
+    )
+
+    modin_result = modin_df.describe()
+    pandas_result = pandas_df.describe()
+
+    df_equals(modin_result, pandas_result)
+
+
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
 @pytest.mark.parametrize("axis", axis_values, ids=axis_keys)
 @pytest.mark.parametrize(