Skip to content

REF: dispatch Series.quantile to DataFrame, remove ScalarBlock #24606

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 4, 2019
3 changes: 1 addition & 2 deletions pandas/core/internals/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
make_block, # io.pytables, io.packers
FloatBlock, IntBlock, ComplexBlock, BoolBlock, ObjectBlock,
TimeDeltaBlock, DatetimeBlock, DatetimeTZBlock,
CategoricalBlock, ExtensionBlock, ScalarBlock,
Block)
CategoricalBlock, ExtensionBlock, Block)
from .managers import ( # noqa:F401
BlockManager, SingleBlockManager,
create_block_manager_from_arrays, create_block_manager_from_blocks,
Expand Down
41 changes: 6 additions & 35 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,6 @@ def make_block(self, values, placement=None, ndim=None):

return make_block(values, placement=placement, ndim=ndim)

def make_block_scalar(self, values):
"""
Create a ScalarBlock
"""
return ScalarBlock(values)

def make_block_same_class(self, values, placement=None, ndim=None,
dtype=None):
""" Wrap given values in a block of same type as self. """
Expand Down Expand Up @@ -1468,13 +1462,15 @@ def quantile(self, qs, interpolation='linear', axis=0):
else:
# create the array of na_values
# 2d len(values) * len(qs)
result = np.repeat(np.array([self._na_value] * len(qs)),
result = np.repeat(np.array([self.fill_value] * len(qs)),
len(values)).reshape(len(values),
len(qs))
else:
mask = isna(self.values)
# asarray needed for Sparse, see GH#24600
# TODO: Why self.values and not values?
mask = np.asarray(isna(self.values))
result = nanpercentile(values, np.array(qs) * 100,
axis=axis, na_value=self._na_value,
axis=axis, na_value=self.fill_value,
mask=mask, ndim=self.ndim,
interpolation=interpolation)

Expand All @@ -1490,8 +1486,6 @@ def quantile(self, qs, interpolation='linear', axis=0):

ndim = getattr(result, 'ndim', None) or 0
result = self._try_coerce_result(result)
if lib.is_scalar(result):
return self.make_block_scalar(result)
return make_block(result,
placement=np.arange(len(result)),
ndim=ndim)
Expand Down Expand Up @@ -1534,29 +1528,6 @@ def _replace_coerce(self, to_replace, value, inplace=True, regex=False,
return self


class ScalarBlock(Block):
"""
a scalar compat Block
"""
__slots__ = ['_mgr_locs', 'values', 'ndim']

def __init__(self, values):
self.ndim = 0
self.mgr_locs = [0]
self.values = values

@property
def dtype(self):
return type(self.values)

@property
def shape(self):
return tuple([0])

def __len__(self):
return 0


class NonConsolidatableMixIn(object):
""" hold methods for the nonconsolidatable blocks """
_can_consolidate = False
Expand Down Expand Up @@ -2675,7 +2646,7 @@ def convert(self, *args, **kwargs):

if args:
raise NotImplementedError
by_item = True if 'by_item' not in kwargs else kwargs['by_item']
by_item = kwargs.get('by_item', True)

new_inputs = ['coerce', 'datetime', 'numeric', 'timedelta']
new_style = False
Expand Down
15 changes: 6 additions & 9 deletions pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ def quantile(self, axis=0, consolidate=True, transposed=False,
Block Manager (new object)
"""

# Series dispatches to DataFrame for quantile, which allows us to
# simplify some of the code here and in the blocks
assert self.ndim >= 2

if consolidate:
self._consolidate_inplace()

Expand All @@ -449,6 +453,7 @@ def get_axe(block, qs, axes):

# note that some DatetimeTZ, Categorical are always ndim==1
ndim = {b.ndim for b in blocks}
assert 0 not in ndim, ndim

if 2 in ndim:

Expand All @@ -474,15 +479,7 @@ def get_axe(block, qs, axes):

return self.__class__(blocks, new_axes)

# 0 ndim
if 0 in ndim and 1 not in ndim:
values = np.array([b.values for b in blocks])
if len(values) == 1:
return values.item()
blocks = [make_block(values, ndim=1)]
axes = Index([ax[0] for ax in axes])

# single block
# single block, i.e. ndim == {1}
values = _concat._concat_compat([b.values for b in blocks])

# compute the orderings of our original data
Expand Down
12 changes: 10 additions & 2 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1987,15 +1987,23 @@ def quantile(self, q=0.5, interpolation='linear'):

self._check_percentile(q)

result = self._data.quantile(qs=q, interpolation=interpolation)
# We dispatch to DataFrame so that core.internals only has to worry
# about 2D cases.
df = self.to_frame()

result = df.quantile(q=q, interpolation=interpolation,
numeric_only=False)
if result.ndim == 2:
result = result.iloc[:, 0]

if is_list_like(q):
result.name = self.name
return self._constructor(result,
index=Float64Index(q),
name=self.name)
else:
# scalar
return result
return result.iloc[0]

def corr(self, other, method='pearson', min_periods=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/resample/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,5 @@ def test_resample_quantile_all_ts(series):
q = 0.75
freq = 'H'
result = s.resample(freq).quantile(q)
expected = s.resample(freq).agg(lambda x: x.quantile(q))
expected = s.resample(freq).agg(lambda x: x.quantile(q)).rename(s.name)
tm.assert_series_equal(result, expected)