diff --git a/doc/source/whatsnew/v0.19.1.txt b/doc/source/whatsnew/v0.19.1.txt index 8bebe5e782e3c..353e7a75dea7b 100644 --- a/doc/source/whatsnew/v0.19.1.txt +++ b/doc/source/whatsnew/v0.19.1.txt @@ -63,12 +63,8 @@ Bug Fixes - Bug in ``MultiIndex.set_levels`` where illegal level values were still set after raising an error (:issue:`13754`) - Bug in ``DataFrame.to_json`` where ``lines=True`` and a value contained a ``}`` character (:issue:`14391`) - Bug in ``df.groupby`` causing an ``AttributeError`` when grouping a single index frame by a column and the index level (:issue`14327`) - - - - - - - - - Bug in ``pd.pivot_table`` may raise ``TypeError`` or ``ValueError`` when ``index`` or ``columns`` is not scalar and ``values`` is not specified (:issue:`14380`) +- Bug in ``pd.pivot_table`` may raise ``TypeError`` or ``ValueError`` when ``index`` or ``columns`` +- Bug in ``pd.to_numeric`` where a 0 was not unsigned on a downcast = 'unsigned' argument (:issue:`14401`) +- Bug in ``pd.pivot_table`` may raise ``TypeError`` or ``ValueError`` when ``index`` or ``columns`` + is not scalar and ``values`` is not specified (:issue:`14380`) diff --git a/pandas/tools/tests/test_util.py b/pandas/tools/tests/test_util.py index 8c16308d79a31..0fe2be5008dae 100644 --- a/pandas/tools/tests/test_util.py +++ b/pandas/tools/tests/test_util.py @@ -401,6 +401,33 @@ def test_downcast(self): res = pd.to_numeric(data, downcast=downcast) tm.assert_numpy_array_equal(res, expected) + def test_downcast_limits(self): + # Test the limits of each downcast. Bug: #14401. + dtype_downcast_min_max = [ + ('int8', 'integer', [np.iinfo(np.int8).min, np.iinfo(np.int8).max]), + ('int16', 'integer', [np.iinfo(np.int16).min, np.iinfo(np.int16).max]), + ('int32', 'integer', [np.iinfo(np.int32).min, np.iinfo(np.int32).max]), + ('int64', 'integer', [np.iinfo(np.int64).min, np.iinfo(np.int64).max]), + ('uint8', 'unsigned', [np.iinfo(np.uint8).min, np.iinfo(np.uint8).max]), + ('uint16', 'unsigned', [np.iinfo(np.uint16).min, np.iinfo(np.uint16).max]), + ('uint32', 'unsigned', [np.iinfo(np.uint32).min, np.iinfo(np.uint32).max]), + # ('uint64', 'unsigned', [np.iinfo(np.uint64).min, np.iinfo(np.uint64).max]), + ('int16', 'integer', [np.iinfo(np.int8).min, np.iinfo(np.int8).max + 1]), + ('int32', 'integer', [np.iinfo(np.int16).min, np.iinfo(np.int16).max + 1]), + ('int64', 'integer', [np.iinfo(np.int32).min, np.iinfo(np.int32).max + 1]), + ('int16', 'integer', [np.iinfo(np.int8).min - 1, np.iinfo(np.int16).max]), + ('int32', 'integer', [np.iinfo(np.int16).min - 1, np.iinfo(np.int32).max]), + ('int64', 'integer', [np.iinfo(np.int32).min - 1, np.iinfo(np.int64).max]), + ('uint16', 'unsigned', [np.iinfo(np.uint8).min, np.iinfo(np.uint8).max + 1]), + ('uint32', 'unsigned', [np.iinfo(np.uint16).min, np.iinfo(np.uint16).max + 1]), + # ('uint64', 'unsigned', [np.iinfo(np.uint32).min, np.iinfo(np.uint32).max + 1]), + ] + + for dtype, downcast, min_max in dtype_downcast_min_max: + series = pd.to_numeric(pd.Series(min_max), downcast=downcast) + tm.assert_equal(series.dtype, dtype) + + if __name__ == '__main__': nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], exit=False) diff --git a/pandas/tools/util.py b/pandas/tools/util.py index fec56328c1721..b50bf9dc448bc 100644 --- a/pandas/tools/util.py +++ b/pandas/tools/util.py @@ -205,7 +205,7 @@ def to_numeric(arg, errors='raise', downcast=None): if downcast in ('integer', 'signed'): typecodes = np.typecodes['Integer'] - elif downcast == 'unsigned' and np.min(values) > 0: + elif downcast == 'unsigned' and np.min(values) >= 0: typecodes = np.typecodes['UnsignedInteger'] elif downcast == 'float': typecodes = np.typecodes['Float']