Skip to content

PERF: remove auto-boxing on isnull/notnull #5154

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 1 commit into from
Oct 8, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ Conversion / Constructors
Series.__init__
Series.astype
Series.copy
Series.isnull
Series.notnull

Indexing, iteration
~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -472,6 +474,8 @@ Conversion / Constructors
DataFrame.astype
DataFrame.convert_objects
DataFrame.copy
DataFrame.isnull
DataFrame.notnull

Indexing, iteration
~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -714,6 +718,8 @@ Conversion / Constructors
Panel.__init__
Panel.astype
Panel.copy
Panel.isnull
Panel.notnull

Getting and setting
~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -976,7 +982,7 @@ Time/Date Components
* **week**: Same as weekofyear
* **dayofweek**: (0=Monday, 6=Sunday)
* **weekday**: (0=Monday, 6=Sunday)
* **dayofyear**
* **dayofyear**
* **quarter**

* **date**: Returns date component of Timestamps
Expand All @@ -990,7 +996,7 @@ Selecting

DatetimeIndex.indexer_at_time
DatetimeIndex.indexer_between_time


Time-specific operations
~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ See :ref:`Internal Refactoring<whatsnew_0130.refactoring>`
- ``filter`` (also added axis argument to selectively filter on a different axis)
- ``reindex,reindex_axis,take``
- ``truncate`` (moved to become part of ``NDFrame``)
- ``isnull/notnull`` now available on ``NDFrame`` objects

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

Expand Down
26 changes: 6 additions & 20 deletions pandas/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def _use_inf_as_null(key):

def _isnull_ndarraylike(obj):

values = obj
values = getattr(obj,'values',obj)
dtype = values.dtype

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

elif dtype in _DATELIKE_DTYPES:
# this is the NaT pattern
v = getattr(values, 'asi8', None)
if v is None:
v = values.view('i8')
result = v == tslib.iNaT
result = values.view('i8') == tslib.iNaT
else:
result = np.isnan(obj)

if isinstance(obj, ABCSeries):
from pandas import Series
result = Series(result, index=obj.index, copy=False)
result = np.isnan(values)

return result


def _isnull_ndarraylike_old(obj):
values = obj
values = getattr(obj,'values',obj)
dtype = values.dtype

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

elif dtype in _DATELIKE_DTYPES:
# this is the NaT pattern
v = getattr(values, 'asi8', None)
if v is None:
v = values.view('i8')
result = v == tslib.iNaT
result = values.view('i8') == tslib.iNaT
else:
result = -np.isfinite(obj)

if isinstance(obj, ABCSeries):
from pandas import Series
result = Series(result, index=obj.index, copy=False)
result = -np.isfinite(values)

return result

Expand Down
12 changes: 12 additions & 0 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2019,6 +2019,18 @@ def interpolate(self, to_replace, method='pad', axis=0, inplace=False,
#----------------------------------------------------------------------
# Action Methods

def isnull(self):
"""
Return a boolean same-sized object indicating if the values are null
"""
return self.__class__(isnull(self),**self._construct_axes_dict())._propogate_attributes(self)

def notnull(self):
"""
Return a boolean same-sized object indicating if the values are not null
"""
return self.__class__(notnull(self),**self._construct_axes_dict())._propogate_attributes(self)

def clip(self, lower=None, upper=None, out=None):
"""
Trim values at input threshold(s)
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ def wrapper(self, other):

# mask out the invalids
if mask.any():
res[mask.values] = masker
res[mask] = masker

return res
return wrapper
Expand Down
3 changes: 0 additions & 3 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2174,9 +2174,6 @@ def dropna(self):

valid = lambda self: self.dropna()

isnull = isnull
notnull = notnull

def first_valid_index(self):
"""
Return label for first non-NA/null value
Expand Down
15 changes: 6 additions & 9 deletions pandas/tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ def test_notnull():
assert result.sum() == 2

with cf.option_context("mode.use_inf_as_null", False):
float_series = Series(np.random.randn(5))
obj_series = Series(np.random.randn(5), dtype=object)
assert(isinstance(notnull(float_series), Series))
assert(isinstance(notnull(obj_series), Series))

for s in [tm.makeFloatSeries(),tm.makeStringSeries(),
tm.makeObjectSeries(),tm.makeTimeSeries(),tm.makePeriodSeries()]:
assert(isinstance(isnull(s), np.ndarray))

def test_isnull():
assert not isnull(1.)
Expand All @@ -77,10 +75,9 @@ def test_isnull():
assert not isnull(np.inf)
assert not isnull(-np.inf)

float_series = Series(np.random.randn(5))
obj_series = Series(np.random.randn(5), dtype=object)
assert(isinstance(isnull(float_series), Series))
assert(isinstance(isnull(obj_series), Series))
for s in [tm.makeFloatSeries(),tm.makeStringSeries(),
tm.makeObjectSeries(),tm.makeTimeSeries(),tm.makePeriodSeries()]:
assert(isinstance(isnull(s), np.ndarray))

# call on DataFrame
df = DataFrame(np.random.randn(10, 5))
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1546,7 +1546,7 @@ def test_set_value_resize(self):
res = self.frame.copy()
res3 = res.set_value('foobar', 'baz', 5)
self.assert_(com.is_float_dtype(res3['baz']))
self.assert_(isnull(res3['baz'].drop(['foobar'])).values.all())
self.assert_(isnull(res3['baz'].drop(['foobar'])).all())
self.assertRaises(ValueError, res3.set_value, 'foobar', 'baz', 'sam')

def test_set_value_with_index_dtype_change(self):
Expand Down
12 changes: 6 additions & 6 deletions pandas/tests/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -3667,17 +3667,17 @@ def test_valid(self):

def test_isnull(self):
ser = Series([0, 5.4, 3, nan, -0.001])
assert_series_equal(
ser.isnull(), Series([False, False, False, True, False]))
np.array_equal(
ser.isnull(), Series([False, False, False, True, False]).values)
ser = Series(["hi", "", nan])
assert_series_equal(ser.isnull(), Series([False, False, True]))
np.array_equal(ser.isnull(), Series([False, False, True]).values)

def test_notnull(self):
ser = Series([0, 5.4, 3, nan, -0.001])
assert_series_equal(
ser.notnull(), Series([True, True, True, False, True]))
np.array_equal(
ser.notnull(), Series([True, True, True, False, True]).values)
ser = Series(["hi", "", nan])
assert_series_equal(ser.notnull(), Series([True, True, False]))
np.array_equal(ser.notnull(), Series([True, True, False]).values)

def test_shift(self):
shifted = self.ts.shift(1)
Expand Down