Skip to content

Commit 6c33b65

Browse files
committed
use datetime64 and timedelta64 to eval
1 parent 2c7c797 commit 6c33b65

File tree

3 files changed

+41
-30
lines changed

3 files changed

+41
-30
lines changed

pandas/core/common.py

+8
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,11 @@ def _pipe(obj, func, *args, **kwargs):
431431
return func(*args, **kwargs)
432432
else:
433433
return func(obj, *args, **kwargs)
434+
435+
436+
# TODO: np.percentile not support datetime64, should be fixed in upsteam.
437+
def percentile(values, q, **kw):
438+
if values.dtype.kind == 'M':
439+
return np.percentile(values.view('i8'), q, **kw).astype(values.dtype)
440+
else:
441+
return np.percentile(values, q, **kw)

pandas/core/internals/blocks.py

+25-28
Original file line numberDiff line numberDiff line change
@@ -1610,12 +1610,12 @@ def _nanpercentile1D(values, mask, q, **kw):
16101610

16111611
if len(values) == 0:
16121612
if lib.is_scalar(q):
1613-
return self._na_value
1613+
return self.fill_value
16141614
else:
1615-
return np.array([self._na_value] * len(q),
1615+
return np.array([self.fill_value] * len(q),
16161616
dtype=values.dtype)
16171617

1618-
return np.percentile(values, q, **kw)
1618+
return com.percentile(values, q, **kw)
16191619

16201620
def _nanpercentile(values, q, axis, **kw):
16211621

@@ -1635,7 +1635,7 @@ def _nanpercentile(values, q, axis, **kw):
16351635
result = np.array(result, dtype=values.dtype, copy=False).T
16361636
return result
16371637
else:
1638-
return np.percentile(values, q, axis=axis, **kw)
1638+
return com.percentile(values, q, axis=axis, **kw)
16391639

16401640
from pandas import Float64Index
16411641
is_empty = values.shape[axis] == 0
@@ -2134,7 +2134,7 @@ def _na_value(self):
21342134

21352135
@property
21362136
def fill_value(self):
2137-
return tslibs.iNaT
2137+
return tslibs.NaT.asm8
21382138

21392139
def get_values(self, dtype=None):
21402140
"""
@@ -2198,25 +2198,21 @@ def _try_coerce_args(self, values, other):
21982198
"""
21992199

22002200
values_mask = isna(values)
2201-
values = values.view('i8')
22022201
other_mask = False
22032202

2204-
if isinstance(other, bool):
2205-
raise TypeError
2206-
elif is_null_datelike_scalar(other):
2207-
other = tslibs.iNaT
2203+
if is_null_datelike_scalar(other):
2204+
other = tslibs.NaT.asm8
22082205
other_mask = True
22092206
elif isinstance(other, Timedelta):
22102207
other_mask = isna(other)
2211-
other = other.value
2208+
other = other.asm8
22122209
elif isinstance(other, timedelta):
2213-
other = Timedelta(other).value
2214-
elif isinstance(other, np.timedelta64):
2215-
other_mask = isna(other)
2216-
other = Timedelta(other).value
2210+
other = np.timedelta64(other)
2211+
elif isinstance(other, (np.timedelta64, np.ndarray)):
2212+
pass
22172213
elif hasattr(other, 'dtype') and is_timedelta64_dtype(other):
22182214
other_mask = isna(other)
2219-
other = other.astype('i8', copy=False).view('i8')
2215+
other = getattr(other, 'values', other)
22202216
else:
22212217
# coercion issues
22222218
# let higher levels handle
@@ -2698,24 +2694,25 @@ def _try_coerce_args(self, values, other):
26982694
"""
26992695

27002696
values_mask = isna(values)
2701-
values = values.view('i8')
27022697
other_mask = False
27032698

2704-
if isinstance(other, bool):
2705-
raise TypeError
2706-
elif is_null_datelike_scalar(other):
2707-
other = tslibs.iNaT
2699+
if getattr(other, 'tz', None) is not None:
2700+
raise TypeError("cannot coerce a Timestamp with a tz on a "
2701+
"naive Block")
2702+
2703+
if is_null_datelike_scalar(other):
2704+
other = tslibs.NaT.asm8
27082705
other_mask = True
2709-
elif isinstance(other, (datetime, np.datetime64, date)):
2710-
other = self._box_func(other)
2711-
if getattr(other, 'tz') is not None:
2712-
raise TypeError("cannot coerce a Timestamp with a tz on a "
2713-
"naive Block")
2706+
elif isinstance(other, tslibs.Timestamp):
27142707
other_mask = isna(other)
2715-
other = other.asm8.view('i8')
2708+
other = other.asm8
2709+
elif isinstance(other, date):
2710+
other = np.datetime64(other)
2711+
elif isinstance(other, (np.datetime64, np.ndarray)):
2712+
pass
27162713
elif hasattr(other, 'dtype') and is_datetime64_dtype(other):
27172714
other_mask = isna(other)
2718-
other = other.astype('i8', copy=False).view('i8')
2715+
other = getattr(other, 'values', other)
27192716
else:
27202717
# coercion issues
27212718
# let higher levels handle

pandas/tests/internals/test_internals.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def test_try_coerce_arg(self):
308308
date(2010, 10, 10))
309309
for val in vals:
310310
coerced = block._try_coerce_args(block.values, val)[2]
311-
assert np.int64 == type(coerced)
311+
assert np.datetime64 == type(coerced)
312312
assert pd.Timestamp('2010-10-10') == pd.Timestamp(coerced)
313313

314314

@@ -1250,14 +1250,20 @@ class TestCanHoldElement(object):
12501250
], ids=lambda x: x.__name__)
12511251
def test_binop_other(self, op, value, dtype):
12521252
skip = {(operator.add, 'bool'),
1253+
(operator.add, '<M8[ns]'),
12531254
(operator.sub, 'bool'),
12541255
(operator.mul, 'bool'),
1256+
(operator.mul, '<m8[ns]'),
1257+
(operator.mul, '<M8[ns]'),
12551258
(operator.truediv, 'bool'),
1259+
(operator.truediv, '<M8[ns]'),
12561260
(operator.mod, 'i8'),
12571261
(operator.mod, 'complex128'),
12581262
(operator.mod, '<M8[ns]'),
12591263
(operator.mod, '<m8[ns]'),
1260-
(operator.pow, 'bool')}
1264+
(operator.pow, 'bool'),
1265+
(operator.pow, '<m8[ns]'),
1266+
(operator.pow, '<M8[ns]')}
12611267
if (op, dtype) in skip:
12621268
pytest.skip("Invalid combination {},{}".format(op, dtype))
12631269
e = DummyElement(value, dtype)

0 commit comments

Comments
 (0)