From 8661bbb60acf6de064624267b7e84b8080ecc424 Mon Sep 17 00:00:00 2001 From: Mitar Date: Mon, 28 May 2018 14:51:00 -0700 Subject: [PATCH] BUG: Support to create DataFrame from list subclasses. Issue: #21226 --- asv_bench/benchmarks/frame_ctor.py | 13 +++++++++++++ doc/source/whatsnew/v0.24.0.rst | 1 + pandas/_libs/lib.pyx | 10 ++++++---- pandas/tests/frame/test_constructors.py | 9 +++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/asv_bench/benchmarks/frame_ctor.py b/asv_bench/benchmarks/frame_ctor.py index 60f6a66e07a7b..dfb6ab5b189b2 100644 --- a/asv_bench/benchmarks/frame_ctor.py +++ b/asv_bench/benchmarks/frame_ctor.py @@ -91,4 +91,17 @@ def time_frame_from_ndarray(self): self.df = DataFrame(self.data) +class FromLists(object): + + goal_time = 0.2 + + def setup(self): + N = 1000 + M = 100 + self.data = [[j for j in range(M)] for i in range(N)] + + def time_frame_from_lists(self): + self.df = DataFrame(self.data) + + from .pandas_vb_common import setup # noqa: F401 diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index cc40e6d42a70b..54faa9ba75d9f 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1606,6 +1606,7 @@ Other - Bug in :meth:`DataFrame.combine_first` in which column types were unexpectedly converted to float (:issue:`20699`) - Bug where C variables were declared with external linkage causing import errors if certain other C libraries were imported before Pandas. (:issue:`24113`) - Constructing a DataFrame with an index argument that wasn't already an instance of :class:`~pandas.core.Index` was broken in `4efb39f `_ (:issue:`22227`). +- Bug in :func:`to_object_array` prevented list subclasses to be used to create :class:`DataFrame` (:issue:`21226`) .. _whatsnew_0.24.0.contributors: diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index 0c081986d83c5..2736133a79d8e 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -2208,7 +2208,7 @@ def map_infer(ndarray arr, object f, bint convert=1): return result -def to_object_array(rows: list, min_width: int=0): +def to_object_array(rows: object, int min_width=0): """ Convert a list of lists into an object array. @@ -2229,20 +2229,22 @@ def to_object_array(rows: list, min_width: int=0): cdef: Py_ssize_t i, j, n, k, tmp ndarray[object, ndim=2] result + list input_rows list row - n = len(rows) + input_rows = rows + n = len(input_rows) k = min_width for i in range(n): - tmp = len(rows[i]) + tmp = len(input_rows[i]) if tmp > k: k = tmp result = np.empty((n, k), dtype=object) for i in range(n): - row = rows[i] + row = input_rows[i] for j in range(len(row)): result[i, j] = row[j] diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index 76e92042cbe6a..fa1117a647850 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -2165,6 +2165,15 @@ def test_constructor_range_dtype(self, dtype): result = DataFrame({'A': range(5)}, dtype=dtype) tm.assert_frame_equal(result, expected) + def test_frame_from_list_subclass(self): + # GH21226 + class List(list): + pass + + expected = DataFrame([[1, 2, 3], [4, 5, 6]]) + result = DataFrame(List([List([1, 2, 3]), List([4, 5, 6])])) + tm.assert_frame_equal(result, expected) + class TestDataFrameConstructorWithDatetimeTZ(TestData):