Repository: modin-project/modin

Issue:
[REFACTOR] Move columnarization to backend
We need to move columnarization part from Series constructor into the backend to allow the OmniSci backend to avoid index accesses on Series construction.


Discussion:

Resolving patch:
diff --git a/modin/backends/base/query_compiler.py b/modin/backends/base/query_compiler.py
--- a/modin/backends/base/query_compiler.py
+++ b/modin/backends/base/query_compiler.py
@@ -303,6 +303,26 @@ def transpose(self, *args, **kwargs):
         """
         pass
 
+    @abc.abstractmethod
+    def columnarize(self):
+        """
+        Transposes this QueryCompiler if it has a single row but multiple columns.
+
+        This method should be called for QueryCompilers representing a Series object,
+        i.e. self.is_series_like() should be True.
+
+        Returns
+        -------
+        BaseQueryCompiler
+            Transposed new QueryCompiler or self.
+        """
+        pass
+
+    @abc.abstractmethod
+    def is_series_like(self):
+        """Return True if QueryCompiler has a single column or row"""
+        pass
+
     # END Abstract Transpose
 
     # Abstract reindex/reset_index (may shuffle data)
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
@@ -507,6 +507,28 @@ def transpose(self, *args, **kwargs):
         # Switch the index and columns and transpose the data within the blocks.
         return self.__constructor__(self._modin_frame.transpose())
 
+    def columnarize(self):
+        """
+        Transposes this QueryCompiler if it has a single row but multiple columns.
+
+        This method should be called for QueryCompilers representing a Series object,
+        i.e. self.is_series_like() should be True.
+
+        Returns
+        -------
+        PandasQueryCompiler
+            Transposed new QueryCompiler or self.
+        """
+        if len(self.columns) != 1 or (
+            len(self.index) == 1 and self.index[0] == "__reduced__"
+        ):
+            return self.transpose()
+        return self
+
+    def is_series_like(self):
+        """Return True if QueryCompiler has a single column or row"""
+        return len(self.columns) == 1 or len(self.index) == 1
+
     # END Transpose
 
     # MapReduce operations
diff --git a/modin/pandas/series.py b/modin/pandas/series.py
--- a/modin/pandas/series.py
+++ b/modin/pandas/series.py
@@ -92,11 +92,7 @@ def __init__(
                     )
                 )
             )._query_compiler
-        if len(query_compiler.columns) != 1 or (
-            len(query_compiler.index) == 1 and query_compiler.index[0] == "__reduced__"
-        ):
-            query_compiler = query_compiler.transpose()
-        self._query_compiler = query_compiler
+        self._query_compiler = query_compiler.columnarize()
         if name is not None:
             self._query_compiler = self._query_compiler
             self.name = name
@@ -148,9 +144,7 @@ def _create_or_update_from_compiler(self, new_query_compiler, inplace=False):
             isinstance(new_query_compiler, type(self._query_compiler))
             or type(new_query_compiler) in self._query_compiler.__class__.__bases__
         ), "Invalid Query Compiler object: {}".format(type(new_query_compiler))
-        if not inplace and (
-            len(new_query_compiler.columns) == 1 or len(new_query_compiler.index) == 1
-        ):
+        if not inplace and new_query_compiler.is_series_like():
             return Series(query_compiler=new_query_compiler)
         elif not inplace:
             # This can happen with things like `reset_index` where we can add columns.


Test patch: