Skip to content

Commit 351097b

Browse files
committed
BUG/DTYPES: preserve bools in convert_objects
1 parent b0c8f51 commit 351097b

File tree

3 files changed

+48
-29
lines changed

3 files changed

+48
-29
lines changed

doc/source/v0.14.1.txt

+2
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,5 @@ Bug Fixes
216216
(:issue:`7408`)
217217
- Bug where ``NaT`` wasn't repr'd correctly in a ``MultiIndex`` (:issue:`7406`,
218218
:issue:`7409`).
219+
- Bug where bool objects were converted to ``nan`` in ``convert_objects``
220+
(:issue:`7416`).

pandas/src/inference.pyx

+34-29
Original file line numberDiff line numberDiff line change
@@ -427,86 +427,91 @@ cdef extern from "parse_helper.h":
427427
cdef double fINT64_MAX = <double> INT64_MAX
428428
cdef double fINT64_MIN = <double> INT64_MIN
429429

430-
def maybe_convert_numeric(ndarray[object] values, set na_values,
431-
convert_empty=True, coerce_numeric=False):
430+
431+
def maybe_convert_numeric(object[:] values, set na_values,
432+
bint convert_empty=True, bint coerce_numeric=False):
432433
'''
433434
Type inference function-- convert strings to numeric (potentially) and
434435
convert to proper dtype array
435436
'''
436437
cdef:
437438
int status
438-
Py_ssize_t i, n
439-
ndarray[float64_t] floats
440-
ndarray[complex128_t] complexes
441-
ndarray[int64_t] ints
442-
bint seen_float = 0
443-
bint seen_complex = 0
439+
Py_ssize_t i, n = values.size
440+
ndarray[float64_t] floats = np.empty(n, dtype='f8')
441+
ndarray[complex128_t] complexes = np.empty(n, dtype='c16')
442+
ndarray[int64_t] ints = np.empty(n, dtype='i8')
443+
ndarray[uint8_t] bools = np.empty(n, dtype='u1')
444+
bint seen_float = False
445+
bint seen_complex = False
446+
bint seen_int = False
447+
bint seen_bool = False
444448
object val
445449
float64_t fval
446450

447-
n = len(values)
448-
449-
floats = np.empty(n, dtype='f8')
450-
complexes = np.empty(n, dtype='c16')
451-
ints = np.empty(n, dtype='i8')
452-
453-
for i from 0 <= i < n:
451+
for i in range(n):
454452
val = values[i]
455453

456454
if val in na_values:
457455
floats[i] = complexes[i] = nan
458-
seen_float = 1
456+
seen_float = True
459457
elif util.is_float_object(val):
460458
floats[i] = complexes[i] = val
461-
seen_float = 1
459+
seen_float = True
462460
elif util.is_integer_object(val):
463461
floats[i] = ints[i] = val
464-
seen_int = 1
462+
seen_int = True
463+
elif util.is_bool_object(val):
464+
floats[i] = ints[i] = bools[i] = val
465+
seen_bool = True
465466
elif val is None:
466467
floats[i] = complexes[i] = nan
467-
seen_float = 1
468-
elif hasattr(val,'__len__') and len(val) == 0:
468+
seen_float = True
469+
elif hasattr(val, '__len__') and len(val) == 0:
469470
if convert_empty or coerce_numeric:
470471
floats[i] = complexes[i] = nan
471-
seen_float = 1
472+
seen_float = True
472473
else:
473474
raise ValueError('Empty string encountered')
474475
elif util.is_complex_object(val):
475476
complexes[i] = val
476-
seen_complex = 1
477+
seen_complex = True
477478
else:
478479
try:
479480
status = floatify(val, &fval)
480481
floats[i] = fval
481482
if not seen_float:
482483
if '.' in val or fval == INF or fval == NEGINF:
483-
seen_float = 1
484+
seen_float = True
484485
elif 'inf' in val: # special case to handle +/-inf
485-
seen_float = 1
486+
seen_float = True
486487
elif fval < fINT64_MAX and fval > fINT64_MIN:
487488
try:
488489
ints[i] = int(val)
489490
except ValueError:
490491
ints[i] = <int64_t> fval
491492
else:
492-
seen_float = 1
493+
seen_float = True
493494
except:
494495
if not coerce_numeric:
495496
raise
496497

497498
floats[i] = nan
498-
seen_float = 1
499-
499+
seen_float = True
500500

501501
if seen_complex:
502502
return complexes
503503
elif seen_float:
504504
return floats
505-
else:
505+
elif seen_int:
506506
return ints
507+
elif seen_bool:
508+
return bools.view(np.bool_)
509+
return ints
510+
507511

508512
def maybe_convert_objects(ndarray[object] objects, bint try_float=0,
509-
bint safe=0, bint convert_datetime=0, bint convert_timedelta=0):
513+
bint safe=0, bint convert_datetime=0,
514+
bint convert_timedelta=0):
510515
'''
511516
Type inference function-- convert object array to proper dtype
512517
'''

pandas/tests/test_series.py

+12
Original file line numberDiff line numberDiff line change
@@ -5025,6 +5025,18 @@ def test_convert_objects(self):
50255025
result = s.convert_objects(convert_dates='coerce')
50265026
assert_series_equal(result, s)
50275027

5028+
def test_convert_objects_preserve_bool(self):
5029+
s = Series([1, True, 3, 5], dtype=object)
5030+
r = s.convert_objects(convert_numeric=True)
5031+
e = Series([1, 1, 3, 5], dtype='i8')
5032+
tm.assert_series_equal(r, e)
5033+
5034+
def test_convert_objects_preserve_all_bool(self):
5035+
s = Series([False, True, False, False], dtype=object)
5036+
r = s.convert_objects(convert_numeric=True)
5037+
e = Series([False, True, False, False], dtype=bool)
5038+
tm.assert_series_equal(r, e)
5039+
50285040
def test_apply_args(self):
50295041
s = Series(['foo,bar'])
50305042

0 commit comments

Comments
 (0)