Skip to content

Commit fe97e1a

Browse files
committed
CLN: add .bool() method for single length evaluation
1 parent 5afd4b4 commit fe97e1a

File tree

8 files changed

+78
-27
lines changed

8 files changed

+78
-27
lines changed

doc/source/basics.rst

+11-2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ Boolean Reductions
219219

220220
.. _basics.reductions:
221221

222-
Furthermore, you can apply the reduction functions: ``any()`` and ``all()`` to provide a
222+
Furthermore, you can apply the reductions: ``empty``, ``any()``, ``all()``, and ``bool()`` to provide a
223223
way to summarize these results.
224224

225225
.. ipython:: python
@@ -233,7 +233,7 @@ You can reduce to a final boolean value.
233233
234234
(df>0).any().any()
235235
236-
Finally you can test if a pandas object is empty, via the ``empty`` property.
236+
You can test if a pandas object is empty, via the ``empty`` property.
237237

238238
.. ipython:: python
239239
@@ -262,6 +262,15 @@ Finally you can test if a pandas object is empty, via the ``empty`` property.
262262
ValueError: The truth value of an array is ambiguous. Use a.empty, a.any() or a.all().
263263
264264
265+
To evaluate single-element pandas objects in a boolean context, use the method ``.bool()``:
266+
267+
.. ipython:: python
268+
269+
Series([True]).bool()
270+
Series([False]).bool()
271+
DataFrame([[True]]).bool()
272+
DataFrame([[False]]).bool()
273+
265274
See :ref:`gotchas<gotchas.truth>` for a more detailed discussion.
266275

267276

doc/source/gotchas.rst

+9
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ or return if ``any`` value is ``True``.
5959
print("I am any")
6060
>>> I am any
6161
62+
To evaluate single-element pandas objects in a boolean context, use the method ``.bool()``:
63+
64+
.. ipython:: python
65+
66+
Series([True]).bool()
67+
Series([False]).bool()
68+
DataFrame([[True]]).bool()
69+
DataFrame([[False]]).bool()
70+
6271
See :ref:`boolean reductions<basics.reductions>` for more examples.
6372

6473
Bitwise boolean

doc/source/release.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,7 @@ API Changes
241241

242242
- Infer and downcast dtype if ``downcast='infer'`` is passed to ``fillna/ffill/bfill`` (:issue:`4604`)
243243
- ``__nonzero__`` for all NDFrame objects, will now raise a ``ValueError``, this reverts back to (:issue:`1073`, :issue:`4633`)
244-
behavior (except for a single-element boolean Series, which mimics ``numpy`` behavior and will evaluate
245-
to the bool of the element)
244+
behavior. Add ``.bool()`` method to ``NDFrame`` objects to facilitate evaluating of single-element boolean Series
246245
- ``DataFrame.update()`` no longer raises a ``DataConflictError``, it now
247246
will raise a ``ValueError`` instead (if necessary) (:issue:`4732`)
248247
- ``Series.isin()`` and ``DataFrame.isin()`` now raise a ``TypeError`` when

doc/source/v0.13.0.txt

+15-2
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ API changes
5555
index.set_names(["bob", "cranberry"], inplace=True)
5656

5757
- Infer and downcast dtype if ``downcast='infer'`` is passed to ``fillna/ffill/bfill`` (:issue:`4604`)
58+
- Remove deprecated ``Factor`` (:issue:`3650`)
59+
- Remove deprecated ``set_printoptions/reset_printoptions`` (:issue:``3046``)
60+
- Remove deprecated ``_verbose_info`` (:issue:`3215`)
5861
- ``__nonzero__`` for all NDFrame objects, will now raise a ``ValueError``, this reverts back to (:issue:`1073`, :issue:`4633`)
59-
behavior (except for a single-element boolean Series, which mimics ``numpy`` behavior and will evaluate
60-
to the bool of the element). See :ref:`gotchas<gotchas.truth>` for a more detailed discussion.
62+
behavior. Added the ``.bool()`` method to ``NDFrame`` objects to facilitate evaluating of single-element boolean Series
63+
See :ref:`gotchas<gotchas.truth>` for a more detailed discussion.
6164

6265
This prevents behaviors like (which will now all raise ``ValueError``)
6366

@@ -69,6 +72,16 @@ API changes
6972
df1 and df2
7073
s1 and s2
7174

75+
76+
To evaluate single-element pandas objects in a boolean context, use the method ``.bool()``:
77+
78+
.. ipython:: python
79+
80+
Series([True]).bool()
81+
Series([False]).bool()
82+
DataFrame([[True]]).bool()
83+
DataFrame([[False]]).bool()
84+
7285
- All non-Index NDFrames (``Series``, ``DataFrame``, ``Panel``, ``Panel4D``,
7386
``SparsePanel``, etc.), now support the entire set of arithmetic operators
7487
and arithmetic flex methods (add, sub, mul, etc.). ``SparsePanel`` does not

pandas/core/generic.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -597,10 +597,24 @@ def empty(self):
597597

598598
def __nonzero__(self):
599599
raise ValueError("The truth value of a {0} is ambiguous. "
600-
"Use a.empty, a.item(), a.any() or a.all().".format(self.__class__.__name__))
600+
"Use a.empty, a.bool(), a.item(), a.any() or a.all().".format(self.__class__.__name__))
601601

602602
__bool__ = __nonzero__
603603

604+
def bool(self):
605+
""" Return the bool of a single element PandasObject
606+
This must be a boolean scalar value, either True or False
607+
608+
Raise a ValueError if the PandasObject does not have exactly
609+
1 element, or that element is not boolean """
610+
v = self.squeeze()
611+
if isinstance(v, (bool,np.bool_)):
612+
return bool(v)
613+
elif np.isscalar(v):
614+
raise ValueError("bool cannot act on a non-boolean single element {0}".format(self.__class__.__name__))
615+
616+
self.__nonzero__()
617+
604618
def __abs__(self):
605619
return self.abs()
606620

pandas/core/series.py

-11
Original file line numberDiff line numberDiff line change
@@ -365,17 +365,6 @@ def imag(self, v):
365365
__long__ = _coerce_method(int)
366366
__int__ = _coerce_method(int)
367367

368-
def __nonzero__(self):
369-
if len(self) == 1 and self.dtype == np.bool_:
370-
warnings.warn("bool on a single-element boolean dtyped Series is deprecated,\n"
371-
" please use a.empty, a.item(), a.any(), or a.all() instead\n",
372-
UserWarning)
373-
return bool(self.iloc[0])
374-
raise ValueError("The truth value of a {0} is ambiguous.\n"
375-
"Use a.empty, a.item(), a.any() or a.all().\n"
376-
"Currently, a boolean Series of length 1 is the exception\n".format(self.__class__.__name__))
377-
__bool__ = __nonzero__
378-
379368
# we are preserving name here
380369
def __getstate__(self):
381370
return dict(_data=self._data, name=self.name)

pandas/io/tests/test_pytables.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -2662,18 +2662,18 @@ def test_select_dtypes(self):
26622662
df = DataFrame(np.random.randn(5,2), columns =['A','B'])
26632663
df['object'] = 'foo'
26642664
df.ix[4:5,'object'] = 'bar'
2665-
df['bool'] = df['A'] > 0
2665+
df['boolv'] = df['A'] > 0
26662666
_maybe_remove(store, 'df')
26672667
store.append('df', df, data_columns = True)
26682668

2669-
expected = df[df.bool == True].reindex(columns=['A','bool'])
2669+
expected = df[df.boolv == True].reindex(columns=['A','boolv'])
26702670
for v in [True,'true',1]:
2671-
result = store.select('df', Term('bool == %s' % str(v)), columns = ['A','bool'])
2671+
result = store.select('df', Term('boolv == %s' % str(v)), columns = ['A','boolv'])
26722672
tm.assert_frame_equal(expected, result)
26732673

2674-
expected = df[df.bool == False ].reindex(columns=['A','bool'])
2674+
expected = df[df.boolv == False ].reindex(columns=['A','boolv'])
26752675
for v in [False,'false',0]:
2676-
result = store.select('df', Term('bool == %s' % str(v)), columns = ['A','bool'])
2676+
result = store.select('df', Term('boolv == %s' % str(v)), columns = ['A','boolv'])
26772677
tm.assert_frame_equal(expected, result)
26782678

26792679
# integer index

pandas/tests/test_generic.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -205,25 +205,30 @@ def test_get_numeric_data_preserve_dtype(self):
205205

206206
def test_nonzero_single_element(self):
207207

208-
# single item to follow numpy
208+
# allow single item via bool method
209209
s = Series([True])
210-
self.assert_(bool(s) == True)
210+
self.assert_(s.bool() is True)
211211

212212
s = Series([False])
213-
self.assert_(bool(s) == False)
213+
self.assert_(s.bool() is False)
214214

215215
# single item nan to raise
216-
for s in [ Series([np.nan]), Series([pd.NaT]) ]:
216+
for s in [ Series([np.nan]), Series([pd.NaT]), Series([True]), Series([False]) ]:
217217
self.assertRaises(ValueError, lambda : bool(s))
218218

219+
for s in [ Series([np.nan]), Series([pd.NaT])]:
220+
self.assertRaises(ValueError, lambda : s.bool())
221+
219222
# multiple bool are still an error
220223
for s in [Series([True,True]), Series([False, False])]:
221224
self.assertRaises(ValueError, lambda : bool(s))
225+
self.assertRaises(ValueError, lambda : s.bool())
222226

223227
# single non-bool are an error
224228
for s in [Series([1]), Series([0]),
225229
Series(['a']), Series([0.0])]:
226230
self.assertRaises(ValueError, lambda : bool(s))
231+
self.assertRaises(ValueError, lambda : s.bool())
227232

228233

229234
class TestDataFrame(unittest.TestCase, Generic):
@@ -235,6 +240,19 @@ def test_rename_mi(self):
235240
index=MultiIndex.from_tuples([("A",x) for x in ["a","B","c"]]))
236241
result = df.rename(str.lower)
237242

243+
def test_nonzero_single_element(self):
244+
245+
# allow single item via bool method
246+
df = DataFrame([[True]])
247+
self.assert_(df.bool() is True)
248+
249+
df = DataFrame([[False]])
250+
self.assert_(df.bool() is False)
251+
252+
df = DataFrame([[False, False]])
253+
self.assertRaises(ValueError, lambda : df.bool())
254+
self.assertRaises(ValueError, lambda : bool(df))
255+
238256
def test_get_numeric_data_preserve_dtype(self):
239257

240258
# get the numeric data

0 commit comments

Comments
 (0)