Skip to content

Commit 35b0b0e

Browse files
committed
Merge pull request #5154 from jreback/perf
PERF: remove auto-boxing on isnull/notnull
2 parents c9d004f + 54db6a6 commit 35b0b0e

File tree

9 files changed

+41
-42
lines changed

9 files changed

+41
-42
lines changed

doc/source/api.rst

+8-2
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ Conversion / Constructors
258258
Series.__init__
259259
Series.astype
260260
Series.copy
261+
Series.isnull
262+
Series.notnull
261263

262264
Indexing, iteration
263265
~~~~~~~~~~~~~~~~~~~
@@ -472,6 +474,8 @@ Conversion / Constructors
472474
DataFrame.astype
473475
DataFrame.convert_objects
474476
DataFrame.copy
477+
DataFrame.isnull
478+
DataFrame.notnull
475479

476480
Indexing, iteration
477481
~~~~~~~~~~~~~~~~~~~
@@ -714,6 +718,8 @@ Conversion / Constructors
714718
Panel.__init__
715719
Panel.astype
716720
Panel.copy
721+
Panel.isnull
722+
Panel.notnull
717723

718724
Getting and setting
719725
~~~~~~~~~~~~~~~~~~~
@@ -976,7 +982,7 @@ Time/Date Components
976982
* **week**: Same as weekofyear
977983
* **dayofweek**: (0=Monday, 6=Sunday)
978984
* **weekday**: (0=Monday, 6=Sunday)
979-
* **dayofyear**
985+
* **dayofyear**
980986
* **quarter**
981987

982988
* **date**: Returns date component of Timestamps
@@ -990,7 +996,7 @@ Selecting
990996

991997
DatetimeIndex.indexer_at_time
992998
DatetimeIndex.indexer_between_time
993-
999+
9941000

9951001
Time-specific operations
9961002
~~~~~~~~~~~~~~~~~~~~~~~~

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ See :ref:`Internal Refactoring<whatsnew_0130.refactoring>`
323323
- ``filter`` (also added axis argument to selectively filter on a different axis)
324324
- ``reindex,reindex_axis,take``
325325
- ``truncate`` (moved to become part of ``NDFrame``)
326+
- ``isnull/notnull`` now available on ``NDFrame`` objects
326327

327328
- These are API changes which make ``Panel`` more consistent with ``DataFrame``
328329

pandas/core/common.py

+6-20
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def _use_inf_as_null(key):
182182

183183
def _isnull_ndarraylike(obj):
184184

185-
values = obj
185+
values = getattr(obj,'values',obj)
186186
dtype = values.dtype
187187

188188
if dtype.kind in ('O', 'S', 'U'):
@@ -198,22 +198,15 @@ def _isnull_ndarraylike(obj):
198198

199199
elif dtype in _DATELIKE_DTYPES:
200200
# this is the NaT pattern
201-
v = getattr(values, 'asi8', None)
202-
if v is None:
203-
v = values.view('i8')
204-
result = v == tslib.iNaT
201+
result = values.view('i8') == tslib.iNaT
205202
else:
206-
result = np.isnan(obj)
207-
208-
if isinstance(obj, ABCSeries):
209-
from pandas import Series
210-
result = Series(result, index=obj.index, copy=False)
203+
result = np.isnan(values)
211204

212205
return result
213206

214207

215208
def _isnull_ndarraylike_old(obj):
216-
values = obj
209+
values = getattr(obj,'values',obj)
217210
dtype = values.dtype
218211

219212
if dtype.kind in ('O', 'S', 'U'):
@@ -229,16 +222,9 @@ def _isnull_ndarraylike_old(obj):
229222

230223
elif dtype in _DATELIKE_DTYPES:
231224
# this is the NaT pattern
232-
v = getattr(values, 'asi8', None)
233-
if v is None:
234-
v = values.view('i8')
235-
result = v == tslib.iNaT
225+
result = values.view('i8') == tslib.iNaT
236226
else:
237-
result = -np.isfinite(obj)
238-
239-
if isinstance(obj, ABCSeries):
240-
from pandas import Series
241-
result = Series(result, index=obj.index, copy=False)
227+
result = -np.isfinite(values)
242228

243229
return result
244230

pandas/core/generic.py

+12
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,18 @@ def interpolate(self, to_replace, method='pad', axis=0, inplace=False,
20192019
#----------------------------------------------------------------------
20202020
# Action Methods
20212021

2022+
def isnull(self):
2023+
"""
2024+
Return a boolean same-sized object indicating if the values are null
2025+
"""
2026+
return self.__class__(isnull(self),**self._construct_axes_dict())._propogate_attributes(self)
2027+
2028+
def notnull(self):
2029+
"""
2030+
Return a boolean same-sized object indicating if the values are not null
2031+
"""
2032+
return self.__class__(notnull(self),**self._construct_axes_dict())._propogate_attributes(self)
2033+
20222034
def clip(self, lower=None, upper=None, out=None):
20232035
"""
20242036
Trim values at input threshold(s)

pandas/core/ops.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ def wrapper(self, other):
539539

540540
# mask out the invalids
541541
if mask.any():
542-
res[mask.values] = masker
542+
res[mask] = masker
543543

544544
return res
545545
return wrapper

pandas/core/series.py

-3
Original file line numberDiff line numberDiff line change
@@ -2174,9 +2174,6 @@ def dropna(self):
21742174

21752175
valid = lambda self: self.dropna()
21762176

2177-
isnull = isnull
2178-
notnull = notnull
2179-
21802177
def first_valid_index(self):
21812178
"""
21822179
Return label for first non-NA/null value

pandas/tests/test_common.py

+6-9
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,9 @@ def test_notnull():
6464
assert result.sum() == 2
6565

6666
with cf.option_context("mode.use_inf_as_null", False):
67-
float_series = Series(np.random.randn(5))
68-
obj_series = Series(np.random.randn(5), dtype=object)
69-
assert(isinstance(notnull(float_series), Series))
70-
assert(isinstance(notnull(obj_series), Series))
71-
67+
for s in [tm.makeFloatSeries(),tm.makeStringSeries(),
68+
tm.makeObjectSeries(),tm.makeTimeSeries(),tm.makePeriodSeries()]:
69+
assert(isinstance(isnull(s), np.ndarray))
7270

7371
def test_isnull():
7472
assert not isnull(1.)
@@ -77,10 +75,9 @@ def test_isnull():
7775
assert not isnull(np.inf)
7876
assert not isnull(-np.inf)
7977

80-
float_series = Series(np.random.randn(5))
81-
obj_series = Series(np.random.randn(5), dtype=object)
82-
assert(isinstance(isnull(float_series), Series))
83-
assert(isinstance(isnull(obj_series), Series))
78+
for s in [tm.makeFloatSeries(),tm.makeStringSeries(),
79+
tm.makeObjectSeries(),tm.makeTimeSeries(),tm.makePeriodSeries()]:
80+
assert(isinstance(isnull(s), np.ndarray))
8481

8582
# call on DataFrame
8683
df = DataFrame(np.random.randn(10, 5))

pandas/tests/test_frame.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ def test_set_value_resize(self):
15461546
res = self.frame.copy()
15471547
res3 = res.set_value('foobar', 'baz', 5)
15481548
self.assert_(com.is_float_dtype(res3['baz']))
1549-
self.assert_(isnull(res3['baz'].drop(['foobar'])).values.all())
1549+
self.assert_(isnull(res3['baz'].drop(['foobar'])).all())
15501550
self.assertRaises(ValueError, res3.set_value, 'foobar', 'baz', 'sam')
15511551

15521552
def test_set_value_with_index_dtype_change(self):

pandas/tests/test_series.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -3667,17 +3667,17 @@ def test_valid(self):
36673667

36683668
def test_isnull(self):
36693669
ser = Series([0, 5.4, 3, nan, -0.001])
3670-
assert_series_equal(
3671-
ser.isnull(), Series([False, False, False, True, False]))
3670+
np.array_equal(
3671+
ser.isnull(), Series([False, False, False, True, False]).values)
36723672
ser = Series(["hi", "", nan])
3673-
assert_series_equal(ser.isnull(), Series([False, False, True]))
3673+
np.array_equal(ser.isnull(), Series([False, False, True]).values)
36743674

36753675
def test_notnull(self):
36763676
ser = Series([0, 5.4, 3, nan, -0.001])
3677-
assert_series_equal(
3678-
ser.notnull(), Series([True, True, True, False, True]))
3677+
np.array_equal(
3678+
ser.notnull(), Series([True, True, True, False, True]).values)
36793679
ser = Series(["hi", "", nan])
3680-
assert_series_equal(ser.notnull(), Series([True, True, False]))
3680+
np.array_equal(ser.notnull(), Series([True, True, False]).values)
36813681

36823682
def test_shift(self):
36833683
shifted = self.ts.shift(1)

0 commit comments

Comments
 (0)