Skip to content

Commit 4061e67

Browse files
committed
BUG: fix issue with sparse concatting
This was originally brought up in :issue:`18686` and :issue:`18914`. Basically the problem is when you use get_dummies with sparse=True it will return a SparseDataFrame with sparse and dense columns. This is in fact not what we want. What we want is a DataFrame with sparse and dense columns. Inside of pandas.core.dtypes.concat is a function that defines the factory class which needed to be changed.
1 parent c19bdc9 commit 4061e67

File tree

5 files changed

+20
-5
lines changed

5 files changed

+20
-5
lines changed

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ Reshaping
363363
- Bug in :func:`Series.rank` where ``Series`` containing ``NaT`` modifies the ``Series`` inplace (:issue:`18521`)
364364
- Bug in :func:`cut` which fails when using readonly arrays (:issue:`18773`)
365365
- Bug in :func:`Dataframe.pivot_table` which fails when the ``aggfunc`` arg is of type string. The behavior is now consistent with other methods like ``agg`` and ``apply`` (:issue:`18713`)
366+
- Bug in :func:`pandas.core.dtypes.concat._get_series_result_type` which returns SparseDataFrame even if not all contained in Frame are sparse. (:issue:`18914` and :issue:`18686`)
366367

367368

368369
Numeric

pandas/core/dtypes/concat.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ def _get_series_result_type(result, objs=None):
8989
def _get_frame_result_type(result, objs):
9090
"""
9191
return appropriate class of DataFrame-like concat
92-
if any block is SparseBlock, return SparseDataFrame
92+
if all blocks are SparseBlock, return SparseDataFrame
9393
otherwise, return 1st obj
9494
"""
95-
if any(b.is_sparse for b in result.blocks):
95+
if result.blocks and all(b.is_sparse for b in result.blocks):
9696
from pandas.core.sparse.api import SparseDataFrame
9797
return SparseDataFrame
9898
else:

pandas/core/sparse/series.py

-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ def __init__(self, data=None, index=None, sparse_index=None, kind='block',
168168
if index is None:
169169
index = data.index.view()
170170
else:
171-
172171
data = data.reindex(index, copy=False)
173172

174173
else:

pandas/tests/reshape/test_reshape.py

+8
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,14 @@ def test_dataframe_dummies_preserve_categorical_dtype(self, dtype):
454454

455455
tm.assert_frame_equal(result, expected)
456456

457+
def test_get_dummies_dont_sparsify_all_columns(self):
458+
# GH18914
459+
df = DataFrame.from_items([('GDP', [1, 2]), ('Nation', ['AB', 'CD'])])
460+
df = get_dummies(df, columns=['Nation'], sparse=True)
461+
df2 = df.reindex(columns=['GDP'])
462+
463+
tm.assert_index_equal(df.index, df2.index)
464+
457465

458466
class TestCategoricalReshape(object):
459467

pandas/tests/sparse/test_combine_concat.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -344,10 +344,17 @@ def test_concat_sparse_dense(self):
344344

345345
res = pd.concat([self.dense3, sparse], axis=1)
346346
exp = pd.concat([self.dense3, self.dense1], axis=1)
347-
assert isinstance(res, pd.SparseDataFrame)
347+
# See GH18914 and #18686 for why this should be
348+
# A DataFrame
349+
assert isinstance(res, pd.DataFrame)
350+
for column in self.dense3.columns:
351+
tm.assert_series_equal(res[column], exp[column])
352+
348353
tm.assert_frame_equal(res, exp)
349354

350355
res = pd.concat([sparse, self.dense3], axis=1)
351356
exp = pd.concat([self.dense1, self.dense3], axis=1)
352-
assert isinstance(res, pd.SparseDataFrame)
357+
assert isinstance(res, pd.DataFrame)
358+
for column in self.dense3.columns:
359+
tm.assert_series_equal(res[column], exp[column])
353360
tm.assert_frame_equal(res, exp)

0 commit comments

Comments
 (0)