Skip to content

Commit c2a481f

Browse files
committed
CLN: make .quantile more datetimelike friendly
1 parent 36a8bd9 commit c2a481f

File tree

3 files changed

+40
-37
lines changed

3 files changed

+40
-37
lines changed

doc/source/whatsnew/v0.18.1.txt

+2-6
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ Bug Fixes
191191

192192
- Bug in ``Timestamp.__repr__`` that caused ``pprint`` to fail in nested structures (:issue:`12622`)
193193
- Bug in ``Timedelta.min`` and ``Timedelta.max``, the properties now report the true minimum/maximum ``timedeltas`` as recognized by Pandas. See :ref:`documentation <timedeltas.limitations>`. (:issue:`12727`)
194+
- Bug in ``.quantile()`` with interpolation may coerce to ``float`` unexpectedly (:issue:`12772`)
195+
- Bug in ``.quantile()`` with empty Series may return scalar rather than empty Series (:issue:`12772`)
194196

195197

196198

@@ -228,9 +230,3 @@ Bug Fixes
228230
- Bug in ``.describe()`` resets categorical columns information (:issue:`11558`)
229231
- Bug where ``loffset`` argument was not applied when calling ``resample().count()`` on a timeseries (:issue:`12725`)
230232
- ``pd.read_excel()`` now accepts path objects (e.g. ``pathlib.Path``, ``py.path.local``) for the file path, in line with other ``read_*`` functions (:issue:`12655`)
231-
232-
233-
234-
235-
- Bug in ``.quantile`` with interpolation may coerce to ``float`` unexpectedly (:issue:`12772`)
236-
- Bug in ``.quantile`` with empty Series may return scalar rather than empty Series (:issue:`12772`)

pandas/core/internals.py

+37-29
Original file line numberDiff line numberDiff line change
@@ -1255,18 +1255,32 @@ def equals(self, other):
12551255
return False
12561256
return array_equivalent(self.values, other.values)
12571257

1258-
def quantile(self, values, qs, **kwargs):
1258+
def quantile(self, qs, mgr=None, **kwargs):
1259+
"""
1260+
compute the quantiles of the
1261+
1262+
Parameters
1263+
----------
1264+
qs : a scalar or list of the quantiles to be computed
1265+
"""
1266+
1267+
values = self.get_values()
1268+
values, mask, _, _ = self._try_coerce_args(values, values)
1269+
if not lib.isscalar(mask) and mask.any():
1270+
values = values[~mask]
1271+
12591272
if len(values) == 0:
12601273
if com.is_list_like(qs):
1261-
return np.array([self.fill_value])
1274+
result = np.array([self.fill_value])
12621275
else:
1263-
return self._na_value
1264-
1265-
if com.is_list_like(qs):
1276+
result = self._na_value
1277+
elif com.is_list_like(qs):
12661278
values = [_quantile(values, x * 100, **kwargs) for x in qs]
1267-
return np.array(values)
1279+
result = np.array(values)
12681280
else:
1269-
return _quantile(values, qs * 100, **kwargs)
1281+
result = _quantile(values, qs * 100, **kwargs)
1282+
1283+
return self._try_coerce_result(result)
12701284

12711285

12721286
class NonConsolidatableMixIn(object):
@@ -1499,22 +1513,6 @@ def get_values(self, dtype=None):
14991513
self._box_func).reshape(self.values.shape)
15001514
return self.values
15011515

1502-
def quantile(self, values, qs, **kwargs):
1503-
values = values.view('i8')
1504-
mask = values == self.fill_value
1505-
if mask.any():
1506-
values = values[~mask]
1507-
result = Block.quantile(self, values, qs, **kwargs)
1508-
1509-
if com.is_datetime64tz_dtype(self):
1510-
# ToDo: Temp logic to avoid GH 12619 and GH 12772
1511-
# which affects to DatetimeBlockTZ_try_coerce_result for np.ndarray
1512-
if isinstance(result, np.ndarray) and values.ndim > 0:
1513-
result = self._holder(result, tz='UTC')
1514-
result = result.tz_convert(self.values.tz)
1515-
return result
1516-
return self._try_coerce_result(result)
1517-
15181516

15191517
class TimeDeltaBlock(DatetimeLikeBlockMixin, IntBlock):
15201518
__slots__ = ()
@@ -2274,12 +2272,14 @@ def _try_coerce_args(self, values, other):
22742272

22752273
def _try_coerce_result(self, result):
22762274
""" reverse of try_coerce_args """
2277-
result = super(DatetimeTZBlock, self)._try_coerce_result(result)
2278-
22792275
if isinstance(result, np.ndarray):
2280-
result = self._holder(result, tz=self.values.tz)
2276+
if result.dtype.kind in ['i', 'f', 'O']:
2277+
result = result.astype('M8[ns]')
22812278
elif isinstance(result, (np.integer, np.float, np.datetime64)):
2282-
result = lib.Timestamp(result, tz=self.values.tz)
2279+
result = lib.Timestamp(result).tz_localize(self.values.tz)
2280+
if isinstance(result, np.ndarray):
2281+
result = self._holder(result).tz_localize(self.values.tz)
2282+
22832283
return result
22842284

22852285
@property
@@ -2806,7 +2806,7 @@ def _verify_integrity(self):
28062806
len(self.items), tot_items))
28072807

28082808
def apply(self, f, axes=None, filter=None, do_integrity_check=False,
2809-
consolidate=True, **kwargs):
2809+
consolidate=True, raw=False, **kwargs):
28102810
"""
28112811
iterate over the blocks, collect and create a new block manager
28122812
@@ -2820,6 +2820,7 @@ def apply(self, f, axes=None, filter=None, do_integrity_check=False,
28202820
integrity check
28212821
consolidate: boolean, default True. Join together blocks having same
28222822
dtype
2823+
raw: boolean, default False. Return the raw returned results
28232824
28242825
Returns
28252826
-------
@@ -2886,7 +2887,11 @@ def apply(self, f, axes=None, filter=None, do_integrity_check=False,
28862887
applied = getattr(b, f)(**kwargs)
28872888
result_blocks = _extend_blocks(applied, result_blocks)
28882889

2889-
if len(result_blocks) == 0:
2890+
if raw:
2891+
if self._is_single_block:
2892+
return result_blocks[0]
2893+
return result_blocks
2894+
elif len(result_blocks) == 0:
28902895
return self.make_empty(axes or self.axes)
28912896
bm = self.__class__(result_blocks, axes or self.axes,
28922897
do_integrity_check=do_integrity_check)
@@ -2902,6 +2907,9 @@ def where(self, **kwargs):
29022907
def eval(self, **kwargs):
29032908
return self.apply('eval', **kwargs)
29042909

2910+
def quantile(self, **kwargs):
2911+
return self.apply('quantile', raw=True, **kwargs)
2912+
29052913
def setitem(self, **kwargs):
29062914
return self.apply('setitem', **kwargs)
29072915

pandas/core/series.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1354,8 +1354,7 @@ def quantile(self, q=0.5, interpolation='linear'):
13541354
if not _np_version_under1p9:
13551355
kwargs.update({'interpolation': interpolation})
13561356

1357-
result = self._data._block.quantile(self.dropna()._values,
1358-
q, **kwargs)
1357+
result = self._data.quantile(qs=q, **kwargs)
13591358

13601359
if com.is_list_like(result):
13611360
# explicitly use Float64Index to coerce empty result to float dtype

0 commit comments

Comments
 (0)