Repository: modin-project/modin
Pull request: FIX-#3619: Fix ValueError when doing loc on empty dataframe
Signed-off-by: Naren Krishna <naren@ponder.io>

<!--
Thank you for your contribution!
Please review the contributing docs: https://modin.readthedocs.io/en/latest/CONTRIBUTING.html
if you have questions about contributing.
-->

## What do these changes do?

<!-- Please give a short brief about these changes. -->

- [x] commit message follows format outlined [here](https://modin.readthedocs.io/en/latest/contributing.html)
- [x] passes `flake8 modin/ asv_bench/benchmarks scripts/doc_checker.py`
- [x] passes `black --check modin/ asv_bench/benchmarks scripts/doc_checker.py`
- [x] signed commit with `git commit -s` <!-- you can amend your commit with a signature via `git commit -amend -s` -->
- [x] Resolves #3619 <!-- issue must be created for each patch -->
- [x] tests added and passing
- [x] module layout described at `docs/developer/architecture.rst` is up-to-date <!-- if you have added, renamed or removed files or directories please update the documentation accordingly -->


Problem statement:
"ValueError: Invalid integer data type 'f'." when doing `loc` on empty dataframe
We currently default to pandas when we're operating on empty dataframes, but this doesn't happen for some properties. `loc` will fail if you try to use it on an empty dataframe.

Reproduction script:

```python
import modin.pandas as pd
import ray
import pandas_market_calendars as mcal
from pandas.tseries.offsets import BusinessDay

import datetime as dt
ENTITIES = ['037833100', '594918104', '023135106', '30231G102', '478160104', '30303M102', '369604103', '00206R102',
          '46625H100', '742718109', '02079K305', '949746101', '931142103', '92343V104', '717081103', '084670702',
          '166764100', '191216100', '458140100', '58933Y105', '68389X105', '060505104', '20030N101', '437076102',
          '92826C839', '17275R102', '718172109', '713448108', '254687106', '459200101', '172967424', '91324P102',
          '031162100', '02209S103', '57636Q104', '88579Y101', '500754106', '806857108', '375558103', '00287Y109',
          '580135101', '126650100', '747525103', '110122108', '931427108', '532457108', '438516106', '913017109',
          '151020104', '097023105', '855244109', '907818108', '654106103', '911312106', '902973304', '741503403',
          '16119P108', '539830109', '882508104', '761713106', 'Y09827109', '38141G104', '609207105', '09062X103',
          '22160K105', '828806109', '194162103', '548661107', '026874784', '002824100', '617446448', '09247X101',
          '260543103', '025816109', '883556102', '887317303', '263534109', '65339F101', '293792107', '26441C204',
          '674599105', '235851102', '842587107', '00724F101', '26875P101', '37045V100', '79466L302', '872540109',
            '49456B101', '20825C104', '59156R108', '70450Y103', '149123101', '25746U109', '345370860', '03027X100',
            '369550108', '517834107', '61166W101', '693475105']


def main():
    nyse = mcal.get_calendar('NYSE')

    trade_date_range = pd.bdate_range(
        end=dt.date.fromisoformat("2017-01-10") - BusinessDay(n=1),
        periods=10,
        freq="C",
        holidays=list(nyse.holidays().holidays),
    )
    trade_date_range.name = "pricing_date"

    pricing_index = pd.MultiIndex.from_product([trade_date_range, ENTITIES], names=["pricing_date", "entity"])

    df = pd.DataFrame(index=pricing_index)

    print(df.loc['2017-01-09'].index.get_level_values("entity"))


if __name__ == '__main__':
    ray.init()
    main()
```

Hints from issue discussion:

Commit message: add for iloc

Signed-off-by: Naren Krishna <naren@ponder.io>

Patch to review:
diff --git a/modin/pandas/indexing.py b/modin/pandas/indexing.py
index aab9469b5f9..d5057e7bf13 100644
--- a/modin/pandas/indexing.py
+++ b/modin/pandas/indexing.py
@@ -528,6 +528,8 @@ def __getitem__(self, key):
             else:
                 result_slice = self.df.columns.slice_locs(col_loc.start, col_loc.stop)
                 return self.df.iloc[:, slice(*result_slice)]
+        if self.df.empty:
+            return self.df._default_to_pandas(lambda df: df.loc[key])
 
         row_lookup, col_lookup = self._compute_lookup(row_loc, col_loc)
         if any(i == -1 for i in row_lookup) or any(i == -1 for i in col_lookup):
@@ -745,6 +747,8 @@ def __getitem__(self, key):
         self.col_scalar = is_scalar(col_loc)
         self._check_dtypes(row_loc)
         self._check_dtypes(col_loc)
+        if self.df.empty:
+            return self.df._default_to_pandas(lambda df: df.iloc[key])
 
         row_lookup, col_lookup = self._compute_lookup(row_loc, col_loc)
         result = super(_iLocIndexer, self).__getitem__(row_lookup, col_lookup, ndim)


Code review comments:
diff_hunk: @@ -528,6 +528,8 @@ def __getitem__(self, key):
             else:
                 result_slice = self.df.columns.slice_locs(col_loc.start, col_loc.stop)
                 return self.df.iloc[:, slice(*result_slice)]
+        if self.df.empty:
+            return self.df._default_to_pandas(lambda df: df.loc[key])
path: modin/pandas/indexing.py
text: @user1:
maybe we should put this at the top of the function, so we make sure that the execution won't go on that probably-failing fast path above?

@author:
Yes, good idea.