Repository: modin-project/modin

Issue:
Exception in .loc assignment when frame is empty
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:

Ubuntu 19.10

- **Modin version** (`modin.__version__`):

0.8.0+71.g2ca3f34

- **Python version**:

Python 3.7.7 :: Intel(R) Corporation

- **Code we can use to reproduce**:

```python
import modin.pandas as pd

df = pd.DataFrame(columns=["col1", "col2"])

df.loc[1] = [11, 22]
print(df)
```

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
<!-- Describe the problem clearly here. -->

On Modin assignment to `.loc` gives me an exception
```
Traceback (most recent call last):
  File "setitem_test.py", line 5, in <module>
    df.loc[1] = [11, 22]
  File "/localdisk/gashiman/modin/modin/pandas/indexing.py", line 302, in __setitem__
    super(_LocIndexer, self).__setitem__(row_lookup, col_lookup, item)
  File "/localdisk/gashiman/modin/modin/pandas/indexing.py", line 175, in __setitem__
    new_qc = self.qc.setitem(1, self.qc.index[row_lookup[0]], item)
  File "/localdisk/gashiman/modin/modin/backends/pandas/query_compiler.py", line 2033, in setitem
    keep_remaining=True,
  File "/localdisk/gashiman/modin/modin/engines/base/frame/data.py", line 1293, in _apply_full_axis_select_indices
    dict_indices = self._get_dict_of_block_index(axis ^ 1, numeric_indices)
  File "/localdisk/gashiman/modin/modin/engines/base/frame/data.py", line 860, in _get_dict_of_block_index
    cumulative = np.append(bins[:-1].cumsum(), np.iinfo(bins.dtype).max)
  File "/nfs/site/home/gashiman/.local/lib/python3.7/site-packages/numpy/core/getlimits.py", line 507, in __init__
    raise ValueError("Invalid integer data type %r." % (self.kind,))
ValueError: Invalid integer data type 'f'.
```

### Source code / logs
<!-- Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. -->



Discussion:
We need a better solution for empty dataframe operations. A meta-issue on this that linked all of the related issues to empty dataframe operations would be really helpful.
BTW workaround for this bug is to specify `index=pd.RangeIndex(...)` inside of DataFrame constructor. In that case there is no exception.
This exception also occurs for indexing on an empty dataframe.

**Modin version**
0.8.1.1+25.g544de0d9

**Python version**
Python 3.8.5

**Code to reproduce**
```
import modin.pandas as pd
df = pd.DataFrame() 
df.iloc[0:100]
```
**Traceback**
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/richard/Documents/CS262/modin/modin/pandas/indexing.py", line 642, in __getitem__
    result = super(_iLocIndexer, self).__getitem__(row_lookup, col_lookup, ndim)
  File "/Users/richard/Documents/CS262/modin/modin/pandas/indexing.py", line 277, in __getitem__
    qc_view = self.qc.view(row_lookup, col_lookup)
  File "/Users/richard/Documents/CS262/modin/modin/backends/pandas/query_compiler.py", line 2764, in view
    self._modin_frame.mask(row_numeric_idx=index, col_numeric_idx=columns)
  File "/Users/richard/Documents/CS262/modin/modin/engines/base/frame/data.py", line 479, in mask
    row_partitions_list = self._get_dict_of_block_index(0, row_numeric_idx)
  File "/Users/richard/Documents/CS262/modin/modin/engines/base/frame/data.py", line 810, in _get_dict_of_block_index
    self._get_dict_of_block_index(axis, [indices.stop]).items()
  File "/Users/richard/Documents/CS262/modin/modin/engines/base/frame/data.py", line 864, in _get_dict_of_block_index
    cumulative = np.append(bins[:-1].cumsum(), np.iinfo(bins.dtype).max)
  File "/Users/richard/.pyenv/versions/ipysheet/lib/python3.8/site-packages/numpy/core/getlimits.py", line 507, in __init__
    raise ValueError("Invalid integer data type %r." % (self.kind,))
ValueError: Invalid integer data type 'f'.
```

Resolving patch:
diff --git a/modin/pandas/indexing.py b/modin/pandas/indexing.py
--- a/modin/pandas/indexing.py
+++ b/modin/pandas/indexing.py
@@ -629,6 +629,16 @@ def __setitem__(self, key, item):
         --------
         pandas.DataFrame.loc
         """
+        if self.df.empty:
+
+            def _loc(df):
+                df.loc[key] = item
+                return df
+
+            self.df._update_inplace(
+                new_query_compiler=self.df._default_to_pandas(_loc)._query_compiler
+            )
+            return
         row_loc, col_loc, _ = self._parse_row_and_column_locators(key)
         if isinstance(row_loc, list) and len(row_loc) == 1:
             if row_loc[0] not in self.qc.index:
@@ -843,6 +853,16 @@ def __setitem__(self, key, item):
         --------
         pandas.DataFrame.iloc
         """
+        if self.df.empty:
+
+            def _iloc(df):
+                df.iloc[key] = item
+                return df
+
+            self.df._update_inplace(
+                new_query_compiler=self.df._default_to_pandas(_iloc)._query_compiler
+            )
+            return
         row_loc, col_loc, _ = self._parse_row_and_column_locators(key)
         row_scalar = is_scalar(row_loc)
         col_scalar = is_scalar(col_loc)


Test patch:
diff --git a/modin/pandas/test/dataframe/test_indexing.py b/modin/pandas/test/dataframe/test_indexing.py
--- a/modin/pandas/test/dataframe/test_indexing.py
+++ b/modin/pandas/test/dataframe/test_indexing.py
@@ -572,6 +572,18 @@ def test_loc_empty():
     df_equals(pandas_df, modin_df)
 
 
+@pytest.mark.parametrize("locator_name", ["iloc", "loc"])
+def test_loc_iloc_2064(locator_name):
+    modin_df, pandas_df = create_test_dfs(columns=["col1", "col2"])
+
+    eval_general(
+        modin_df,
+        pandas_df,
+        lambda df: getattr(df, locator_name).__setitem__([1], [11, 22]),
+        __inplace__=True,
+    )
+
+
 @pytest.mark.parametrize("index", [["row1", "row2", "row3"]])
 @pytest.mark.parametrize("columns", [["col1", "col2"]])
 def test_loc_assignment(index, columns):