From b47d5fd859669abe73dd729d6ed8ea9850912934 Mon Sep 17 00:00:00 2001 From: Marc Garcia Date: Fri, 26 Jan 2018 16:55:17 +0000 Subject: [PATCH] BUG adding support for dense Series in the SparseDataFrame constructor, and providing useful error messages for other types (#19374) --- doc/source/whatsnew/v0.23.0.txt | 2 +- pandas/core/sparse/frame.py | 7 +++++++ pandas/tests/sparse/frame/test_frame.py | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 4dde76dee46a5..246eab386b2ab 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -512,7 +512,7 @@ Groupby/Resample/Rolling Sparse ^^^^^^ -- +- Bug in which creating a ``SparseDataFrame`` from a dense ``Series`` or an unsupported type raised an uncontrolled exception (:issue:`19374`) - - diff --git a/pandas/core/sparse/frame.py b/pandas/core/sparse/frame.py index c7f5b0ba67c19..eb3184f371a0c 100644 --- a/pandas/core/sparse/frame.py +++ b/pandas/core/sparse/frame.py @@ -95,6 +95,9 @@ def __init__(self, data=None, index=None, columns=None, default_kind=None, dtype=dtype, copy=copy) elif isinstance(data, DataFrame): mgr = self._init_dict(data, data.index, data.columns, dtype=dtype) + elif isinstance(data, Series): + mgr = self._init_dict(data.to_frame(), data.index, + columns=None, dtype=dtype) elif isinstance(data, BlockManager): mgr = self._init_mgr(data, axes=dict(index=index, columns=columns), dtype=dtype, copy=copy) @@ -116,6 +119,10 @@ def __init__(self, data=None, index=None, columns=None, default_kind=None, mgr = to_manager(data, columns, index) if dtype is not None: mgr = mgr.astype(dtype) + else: + msg = ('SparseDataFrame called with unkown type "{data_type}" ' + 'for data argument') + raise TypeError(msg.format(data_type=type(data).__name__)) generic.NDFrame.__init__(self, mgr) diff --git a/pandas/tests/sparse/frame/test_frame.py b/pandas/tests/sparse/frame/test_frame.py index 058892e3b85ff..2b589ebd4735e 100644 --- a/pandas/tests/sparse/frame/test_frame.py +++ b/pandas/tests/sparse/frame/test_frame.py @@ -199,6 +199,29 @@ def test_constructor_from_series(self): # without sparse value raises error # df2 = SparseDataFrame([x2_sparse, y]) + def test_constructor_from_dense_series(self): + # GH 19393 + # series with name + x = Series(np.random.randn(10000), name='a') + result = SparseDataFrame(x) + expected = x.to_frame().to_sparse() + tm.assert_sp_frame_equal(result, expected) + + # series with no name + x = Series(np.random.randn(10000)) + result = SparseDataFrame(x) + expected = x.to_frame().to_sparse() + tm.assert_sp_frame_equal(result, expected) + + def test_constructor_from_unknown_type(self): + # GH 19393 + class Unknown: + pass + with pytest.raises(TypeError, + message='SparseDataFrame called with unkown type ' + '"Unknown" for data argument'): + SparseDataFrame(Unknown()) + def test_constructor_preserve_attr(self): # GH 13866 arr = pd.SparseArray([1, 0, 3, 0], dtype=np.int64, fill_value=0)