Repository: modin-project/modin

Issue:
DataFrame.loc fails when passing a boolean
### System information
OS Platform and Distribution: Manjaro Linux
Modin installed from: pip
Modin version: 0.7.0
Python version: 3.7.4

### Describe the problem
DataFrame.loc operation fails when passing a boolean.
It seems like when passing a boolean list for one of the parameters, it expects the parameters to be switched in order. Instead of DataFrame.loc(rows, columns) it expects DataFrame.loc(columns, rows)

### Source code / logs
#### Code
```
import pandas as pd
import modin.pandas as mpd


df = pd.DataFrame([[1, 2], [4, 5], [7, 8]],
                  index=['cobra', 'viper', 'sidewinder'],
                  columns=['max_speed', 'shield'])

o = df.loc[:, ~df.columns.duplicated()]

print(f'Pandas:\n{o}')

mdf = mpd.DataFrame([[1, 2], [4, 5], [7, 8]],
                    index=['cobra', 'viper', 'sidewinder'],
                    columns=['max_speed', 'shield'])

o = mdf.loc[:, ~mdf.columns.duplicated()]

print(f'Modin:\n{o}')

```
#### Output
```
Pandas:
            max_speed  shield
cobra               1       2
viper               4       5
sidewinder          7       8
UserWarning: Distributing <class 'list'> object. This may take some time.
Traceback (most recent call last):
  File "modint.py", line 17, in <module>
    o = mdf.loc[:, ~mdf.columns.duplicated()]
  File "/opt/anaconda/lib/python3.7/site-packages/modin/pandas/indexing.py", line 216, in __getitem__
    return self.df.__getitem__(key[1])
  File "/opt/anaconda/lib/python3.7/site-packages/modin/pandas/base.py", line 3304, in __getitem__
    return self._getitem(key)
  File "/opt/anaconda/lib/python3.7/site-packages/modin/pandas/dataframe.py", line 1896, in _getitem
    return self._getitem_array(key)
  File "/opt/anaconda/lib/python3.7/site-packages/modin/pandas/dataframe.py", line 1926, in _getitem_array
    len(key), len(self.index)
ValueError: Item wrong length 2 instead of 3.
```


Discussion:
Hi @freedumb2000, thanks for reporting!

The source of the issue is not that the `DataFrame.loc` expects (columns, rows), it is that when no rows are provided we reroute to `DataFrame.__getitem__` to reduce code and reuse implementation. However in the case of a boolean mask, `__getitem__` will apply that to the rows. 

The fix is to special case the boolean mask within `loc`. Thanks for finding and reporting this!

Resolving patch:
diff --git a/modin/pandas/indexing.py b/modin/pandas/indexing.py
--- a/modin/pandas/indexing.py
+++ b/modin/pandas/indexing.py
@@ -211,8 +211,13 @@ def __getitem__(self, key):
         else:
             if len(key) > self.df.ndim:
                 raise IndexingError("Too many indexers")
+            # If we're only slicing columns, handle the case with `__getitem__`
             if isinstance(key[0], slice) and key[0] == slice(None):
                 if not isinstance(key[1], slice):
+                    # Boolean indexers can just be sliced into the columns object and
+                    # then passed to `__getitem__`
+                    if is_boolean_array(key[1]):
+                        return self.df.__getitem__(self.df.columns[key[1]])
                     return self.df.__getitem__(key[1])
                 else:
                     result_slice = self.df.columns.slice_locs(key[1].start, key[1].stop)


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
@@ -4438,16 +4438,20 @@ def test_loc(self, request, data):
             df_equals(modin_df.loc[[1, 2]], pandas_df.loc[[1, 2]])
 
             # List-like of booleans
-            indices = [
-                True if i % 3 == 0 else False for i in range(len(modin_df.index))
-            ]
-            columns = [
-                True if i % 5 == 0 else False for i in range(len(modin_df.columns))
-            ]
+            indices = [i % 3 == 0 for i in range(len(modin_df.index))]
+            columns = [i % 5 == 0 for i in range(len(modin_df.columns))]
             modin_result = modin_df.loc[indices, columns]
             pandas_result = pandas_df.loc[indices, columns]
             df_equals(modin_result, pandas_result)
 
+            modin_result = modin_df.loc[:, columns]
+            pandas_result = pandas_df.loc[:, columns]
+            df_equals(modin_result, pandas_result)
+
+            modin_result = modin_df.loc[indices]
+            pandas_result = pandas_df.loc[indices]
+            df_equals(modin_result, pandas_result)
+
             # See issue #80
             # df_equals(modin_df.loc[[1, 2], ['col1']], pandas_df.loc[[1, 2], ['col1']])
             df_equals(modin_df.loc[1:2, key1:key2], pandas_df.loc[1:2, key1:key2])