Repository: modin-project/modin

Issue:
DataFrame.shift(0) and Series.shift(0) produce ValueError
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:

Ubuntu 20.04

- **Modin version** (`modin.__version__`):

0.7.3+110.g6637572

- **Python version**:

Python 3.8.2

- **Code we can use to reproduce**:

```python
import numpy as np
import modin.pandas as pd

df1 = pd.DataFrame({"column": [11, 22, 33, 44, 55]}, index=[2, 3, 4, 5, 6])
print(df1)

df2 = df1.shift(0)
print(df2)

s1 = df["column"]
s2 = s1.shift(0)
print(s2)
```

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
<!-- Describe the problem clearly here. -->

Running the above code produce `ValueError` on Modin.

### 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:

Resolving patch:
diff --git a/modin/pandas/base.py b/modin/pandas/base.py
--- a/modin/pandas/base.py
+++ b/modin/pandas/base.py
@@ -2579,20 +2579,31 @@ def shift(self, periods=1, freq=None, axis=0, fill_value=None):
             Copy of input object, shifted.
         """
 
-        fill_index = (
-            pandas.RangeIndex(start=0, stop=abs(periods), step=1)
-            if axis == "index" or axis == 0
-            else self.index
-        )
+        if periods == 0:
+            # Check obvious case first
+            return self.copy()
+
+        empty_frame = False
+        if axis == "index" or axis == 0:
+            if abs(periods) >= len(self.index):
+                fill_index = self.index
+                empty_frame = True
+            else:
+                fill_index = pandas.RangeIndex(start=0, stop=abs(periods), step=1)
+        else:
+            fill_index = self.index
         from .dataframe import DataFrame
 
         fill_columns = None
         if isinstance(self, DataFrame):
-            fill_columns = (
-                pandas.RangeIndex(start=0, stop=abs(periods), step=1)
-                if axis == "columns" or axis == 1
-                else self.columns
-            )
+            if axis == "columns" or axis == 1:
+                if abs(periods) >= len(self.columns):
+                    fill_columns = self.columns
+                    empty_frame = True
+                else:
+                    fill_columns = pandas.RangeIndex(start=0, stop=abs(periods), step=1)
+            else:
+                fill_columns = self.columns
 
         filled_df = (
             self.__constructor__(index=fill_index, columns=fill_columns)
@@ -2602,15 +2613,24 @@ def shift(self, periods=1, freq=None, axis=0, fill_value=None):
         if fill_value is not None:
             filled_df.fillna(fill_value, inplace=True)
 
+        if empty_frame:
+            return filled_df
+
         if freq is None:
             if axis == "index" or axis == 0:
                 if periods > 0:
                     dropped_df = self.drop(self.index[-periods:])
                     new_frame = filled_df.append(dropped_df, ignore_index=True)
+                    new_frame.index = self.index.copy()
+                    if isinstance(self, DataFrame):
+                        new_frame.columns = self.columns.copy()
                     return new_frame
                 else:
                     dropped_df = self.drop(self.index[:-periods])
                     new_frame = dropped_df.append(filled_df, ignore_index=True)
+                    new_frame.index = self.index.copy()
+                    if isinstance(self, DataFrame):
+                        new_frame.columns = self.columns.copy()
                     return new_frame
             else:
                 res_columns = self.columns


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
@@ -2506,19 +2506,26 @@ def test_sem(self):
             pd.DataFrame(data).sem()
 
     @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
-    def test_shift(self, data):
-        modin_df = pd.DataFrame(data)
-        pandas_df = pandas.DataFrame(data)
+    @pytest.mark.parametrize("index", ["default", "ndarray"])
+    @pytest.mark.parametrize("axis", [0, 1])
+    @pytest.mark.parametrize("periods", [0, 1, -1, 10, -10, 1000000000, -1000000000])
+    def test_shift(self, data, index, axis, periods):
+        if index == "default":
+            modin_df = pd.DataFrame(data)
+            pandas_df = pandas.DataFrame(data)
+        elif index == "ndarray":
+            data_column_length = len(data[next(iter(data))])
+            index_data = np.arange(2, data_column_length + 2)
+            modin_df = pd.DataFrame(data, index=index_data)
+            pandas_df = pandas.DataFrame(data, index=index_data)
 
-        df_equals(modin_df.shift(), pandas_df.shift())
-        df_equals(modin_df.shift(fill_value=777), pandas_df.shift(fill_value=777))
-        df_equals(modin_df.shift(periods=7), pandas_df.shift(periods=7))
         df_equals(
-            modin_df.shift(periods=-3, axis=0), pandas_df.shift(periods=-3, axis=0)
+            modin_df.shift(periods=periods, axis=axis),
+            pandas_df.shift(periods=periods, axis=axis),
         )
-        df_equals(modin_df.shift(periods=5, axis=1), pandas_df.shift(periods=5, axis=1))
         df_equals(
-            modin_df.shift(periods=-5, axis=1), pandas_df.shift(periods=-5, axis=1)
+            modin_df.shift(periods=periods, axis=axis, fill_value=777),
+            pandas_df.shift(periods=periods, axis=axis, fill_value=777),
         )
 
     def test_slice_shift(self):