From d8ded3eb203e0fa9cdac49ada59048d6f46ab128 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Mon, 8 Mar 2021 13:32:11 +0100 Subject: [PATCH] [ArrayManager] Add Series._as_manager (consolidate with DataFrame) --- pandas/core/frame.py | 20 ----------------- pandas/core/generic.py | 19 ++++++++++++++++ pandas/core/internals/construction.py | 22 ++++++++++++++----- pandas/tests/internals/test_managers.py | 29 +++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 38cd730efabd1..78ffcd4cdf720 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -67,7 +67,6 @@ IndexKeyFunc, IndexLabel, Level, - Manager, NpDtype, PythonFuncType, Renamer, @@ -668,25 +667,6 @@ def __init__( NDFrame.__init__(self, mgr) - def _as_manager(self, typ: str) -> DataFrame: - """ - Private helper function to create a DataFrame with specific manager. - - Parameters - ---------- - typ : {"block", "array"} - - Returns - ------- - DataFrame - New DataFrame using specified manager type. Is not guaranteed - to be a copy or not. - """ - new_mgr: Manager - new_mgr = mgr_to_mgr(self._mgr, typ=typ) - # fastpath of passing a manager doesn't check the option/manager class - return DataFrame(new_mgr) - # ---------------------------------------------------------------------- @property diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 327a69e7f3fb4..6430148b47c58 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -293,6 +293,25 @@ def _from_mgr(cls, mgr: Manager): object.__setattr__(obj, "_attrs", {}) return obj + def _as_manager(self: FrameOrSeries, typ: str) -> FrameOrSeries: + """ + Private helper function to create a DataFrame with specific manager. + + Parameters + ---------- + typ : {"block", "array"} + + Returns + ------- + DataFrame + New DataFrame using specified manager type. Is not guaranteed + to be a copy or not. + """ + new_mgr: Manager + new_mgr = mgr_to_mgr(self._mgr, typ=typ) + # fastpath of passing a manager doesn't check the option/manager class + return self._constructor(new_mgr).__finalize__(self) + # ---------------------------------------------------------------------- # attrs and flags diff --git a/pandas/core/internals/construction.py b/pandas/core/internals/construction.py index c314673f609f3..833d9c19cbfd7 100644 --- a/pandas/core/internals/construction.py +++ b/pandas/core/internals/construction.py @@ -72,13 +72,17 @@ get_objs_combined_axis, union_indexes, ) -from pandas.core.internals.array_manager import ArrayManager +from pandas.core.internals.array_manager import ( + ArrayManager, + SingleArrayManager, +) from pandas.core.internals.blocks import ( ensure_block_shape, new_block, ) from pandas.core.internals.managers import ( BlockManager, + SingleBlockManager, create_block_manager_from_arrays, create_block_manager_from_blocks, ) @@ -202,15 +206,21 @@ def mgr_to_mgr(mgr, typ: str): if isinstance(mgr, BlockManager): new_mgr = mgr else: - new_mgr = arrays_to_mgr( - mgr.arrays, mgr.axes[0], mgr.axes[1], mgr.axes[0], typ="block" - ) + if mgr.ndim == 2: + new_mgr = arrays_to_mgr( + mgr.arrays, mgr.axes[0], mgr.axes[1], mgr.axes[0], typ="block" + ) + else: + new_mgr = SingleBlockManager.from_array(mgr.arrays[0], mgr.index) elif typ == "array": if isinstance(mgr, ArrayManager): new_mgr = mgr else: - arrays = [mgr.iget_values(i).copy() for i in range(len(mgr.axes[0]))] - new_mgr = ArrayManager(arrays, [mgr.axes[1], mgr.axes[0]]) + if mgr.ndim == 2: + arrays = [mgr.iget_values(i).copy() for i in range(len(mgr.axes[0]))] + new_mgr = ArrayManager(arrays, [mgr.axes[1], mgr.axes[0]]) + else: + new_mgr = SingleArrayManager([mgr.internal_values()], [mgr.index]) else: raise ValueError(f"'typ' needs to be one of {{'block', 'array'}}, got '{typ}'") return new_mgr diff --git a/pandas/tests/internals/test_managers.py b/pandas/tests/internals/test_managers.py index 4ca6e8b6598aa..045c3cbb18ba6 100644 --- a/pandas/tests/internals/test_managers.py +++ b/pandas/tests/internals/test_managers.py @@ -8,6 +8,8 @@ from pandas.core.internals import ( ArrayManager, BlockManager, + SingleArrayManager, + SingleBlockManager, ) @@ -41,3 +43,30 @@ def test_dataframe_creation(): assert isinstance(result._mgr, BlockManager) tm.assert_frame_equal(result, df_array) assert len(result._mgr.blocks) == 2 + + +def test_series_creation(): + + with pd.option_context("mode.data_manager", "block"): + s_block = pd.Series([1, 2, 3], name="A", index=["a", "b", "c"]) + assert isinstance(s_block._mgr, SingleBlockManager) + + with pd.option_context("mode.data_manager", "array"): + s_array = pd.Series([1, 2, 3], name="A", index=["a", "b", "c"]) + assert isinstance(s_array._mgr, SingleArrayManager) + + # also ensure both are seen as equal + tm.assert_series_equal(s_block, s_array) + + # conversion from one manager to the other + result = s_block._as_manager("block") + assert isinstance(result._mgr, SingleBlockManager) + result = s_block._as_manager("array") + assert isinstance(result._mgr, SingleArrayManager) + tm.assert_series_equal(result, s_block) + + result = s_array._as_manager("array") + assert isinstance(result._mgr, SingleArrayManager) + result = s_array._as_manager("block") + assert isinstance(result._mgr, SingleBlockManager) + tm.assert_series_equal(result, s_array)