Skip to content

Commit 5ea9d01

Browse files
committed
Merge pull request #3312 from jreback/GH3311
BUG: GH3311 Dataframe where with a datetimelike was not correctly selecting
2 parents 6124e13 + 91f9a6d commit 5ea9d01

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

RELEASE.rst

+2
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ pandas 0.11.0
292292
spacing (GH3258_)
293293
- fixed pretty priniting of sets (GH3294_)
294294
- Panel() and Panel.from_dict() now respects ordering when give OrderedDict (GH3303_)
295+
- DataFrame where with a datetimelike incorrectly selecting (GH3311_)
295296

296297
.. _GH3294: https://github.com/pydata/pandas/issues/3294
297298
.. _GH622: https://github.com/pydata/pandas/issues/622
@@ -400,6 +401,7 @@ pandas 0.11.0
400401
.. _GH3258: https://github.com/pydata/pandas/issues/3258
401402
.. _GH3283: https://github.com/pydata/pandas/issues/3283
402403
.. _GH2919: https://github.com/pydata/pandas/issues/2919
404+
.. _GH3311: https://github.com/pydata/pandas/issues/3311
403405

404406
pandas 0.10.1
405407
=============

pandas/core/internals.py

+35-2
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,14 @@ def _try_cast_result(self, result):
284284
we may have roundtripped thru object in the mean-time """
285285
return result
286286

287+
def _try_coerce_args(self, values, other):
288+
""" provide coercion to our input arguments """
289+
return values, other
290+
291+
def _try_coerce_result(self, result):
292+
""" reverse of try_coerce_args """
293+
return result
294+
287295
def to_native_types(self, slicer=None, na_rep='', **kwargs):
288296
""" convert to our native types format, slicing if desired """
289297

@@ -454,9 +462,10 @@ def eval(self, func, other, raise_on_error = True, try_cast = False):
454462
values = values.T
455463
is_transposed = True
456464

465+
values, other = self._try_coerce_args(values, other)
457466
args = [ values, other ]
458467
try:
459-
result = func(*args)
468+
result = self._try_coerce_result(func(*args))
460469
except (Exception), detail:
461470
if raise_on_error:
462471
raise TypeError('Could not operate [%s] with block values [%s]'
@@ -529,8 +538,9 @@ def func(c,v,o):
529538
if c.ravel().all():
530539
return v
531540

541+
v, o = self._try_coerce_args(v, o)
532542
try:
533-
return expressions.where(c, v, o, raise_on_error=True)
543+
return self._try_coerce_result(expressions.where(c, v, o, raise_on_error=True))
534544
except (Exception), detail:
535545
if raise_on_error:
536546
raise TypeError('Could not operate [%s] with block values [%s]'
@@ -735,6 +745,29 @@ def _try_cast(self, element):
735745
except:
736746
return element
737747

748+
def _try_coerce_args(self, values, other):
749+
""" provide coercion to our input arguments
750+
we are going to compare vs i8, so coerce to integer
751+
values is always ndarra like, other may not be """
752+
values = values.view('i8')
753+
if isinstance(other, datetime):
754+
other = lib.Timestamp(other).asm8.view('i8')
755+
elif isnull(other):
756+
other = tslib.iNaT
757+
else:
758+
other = other.view('i8')
759+
760+
return values, other
761+
762+
def _try_coerce_result(self, result):
763+
""" reverse of try_coerce_args """
764+
if isinstance(result, np.ndarray):
765+
if result.dtype == 'i8':
766+
result = tslib.array_to_datetime(result.astype(object).ravel()).reshape(result.shape)
767+
elif isinstance(result, np.integer):
768+
result = lib.Timestamp(result)
769+
return result
770+
738771
def to_native_types(self, slicer=None, na_rep=None, **kwargs):
739772
""" convert to our native types format, slicing if desired """
740773

pandas/tests/test_frame.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import pandas.core.datetools as datetools
2323
from pandas.core.api import (DataFrame, Index, Series, notnull, isnull,
2424
MultiIndex, DatetimeIndex, Timestamp, Period)
25+
from pandas import date_range
2526
from pandas.io.parsers import read_csv
2627

2728
from pandas.util.testing import (assert_almost_equal,
@@ -2197,7 +2198,6 @@ def test_constructor_error_msgs(self):
21972198
self.assert_("Mixing dicts with non-Series may lead to ambiguous ordering." in str(detail))
21982199

21992200
# wrong size ndarray, GH 3105
2200-
from pandas import date_range
22012201
try:
22022202
DataFrame(np.arange(12).reshape((4, 3)), columns=['foo', 'bar', 'baz'],
22032203
index=date_range('2000-01-01', periods=3))
@@ -2888,7 +2888,6 @@ def test_constructor_with_datetimes(self):
28882888
assert_series_equal(result, expected)
28892889

28902890
# GH 2809
2891-
from pandas import date_range
28922891
ind = date_range(start="2000-01-01", freq="D", periods=10)
28932892
datetimes = [ts.to_pydatetime() for ts in ind]
28942893
datetime_s = Series(datetimes)
@@ -2975,7 +2974,6 @@ def test_constructor_for_list_with_dtypes(self):
29752974

29762975
def test_timedeltas(self):
29772976

2978-
from pandas import date_range
29792977
df = DataFrame(dict(A = Series(date_range('2012-1-1', periods=3, freq='D')),
29802978
B = Series([ timedelta(days=i) for i in range(3) ])))
29812979
result = df.get_dtype_counts()
@@ -3001,7 +2999,6 @@ def test_timedeltas(self):
30012999

30023000
def test_operators_timedelta64(self):
30033001

3004-
from pandas import date_range
30053002
from datetime import datetime, timedelta
30063003
df = DataFrame(dict(A = date_range('2012-1-1', periods=3, freq='D'),
30073004
B = date_range('2012-1-2', periods=3, freq='D'),
@@ -6838,6 +6835,19 @@ def test_where_bug(self):
68386835
result.where(result > 2, np.nan, inplace=True)
68396836
assert_frame_equal(result, expected)
68406837

6838+
def test_where_datetime(self):
6839+
6840+
# GH 3311
6841+
df = DataFrame(dict(A = date_range('20130102',periods=5),
6842+
B = date_range('20130104',periods=5),
6843+
C = np.random.randn(5)))
6844+
6845+
stamp = datetime(2013,1,3)
6846+
result = df[df>stamp]
6847+
expected = df.copy()
6848+
expected.loc[[0,1],'A'] = np.nan
6849+
assert_frame_equal(result,expected)
6850+
68416851
def test_mask(self):
68426852
df = DataFrame(np.random.randn(5, 3))
68436853
cond = df > 0

0 commit comments

Comments
 (0)