From 75a916a038c62400aa6431c8e9a2deb6e86a350e Mon Sep 17 00:00:00 2001 From: Viktor Kerkez Date: Fri, 20 Sep 2013 20:57:05 +0200 Subject: [PATCH] Fixed issue #4902. Extended _ensure_numeric to check if the value is a complex numbers. Also it now tries to convert the value to a complex number if conversion to float fails. Added PyDev project files to .gitignore. --- .gitignore | 3 +++ doc/source/release.rst | 1 + pandas/core/nanops.py | 8 +++--- pandas/tests/test_common.py | 49 +++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 3da165e07c77c..df7002a79d974 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ pandas/io/*.json .vagrant *.whl **/wheelhouse/* + +.project +.pydevproject diff --git a/doc/source/release.rst b/doc/source/release.rst index ffb792ca98da5..1e1b665a478a1 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -433,6 +433,7 @@ Bug Fixes - Fix an issue in TextFileReader w/ Python engine (i.e. PythonParser) with thousands != "," (:issue:`4596`) - Bug in getitem with a duplicate index when using where (:issue:`4879`) + - Fixed ``_ensure_numeric`` does not check for complex numbers (:issue:`4902`) pandas 0.12.0 diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index 3a185ca83604d..247f429d4b331 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -546,12 +546,14 @@ def _ensure_numeric(x): if isinstance(x, np.ndarray): if x.dtype == np.object_: x = x.astype(np.float64) - elif not (com.is_float(x) or com.is_integer(x)): + elif not (com.is_float(x) or com.is_integer(x) or com.is_complex(x)): try: x = float(x) except Exception: - raise TypeError('Could not convert %s to numeric' % str(x)) - + try: + x = complex(x) + except Exception: + raise TypeError('Could not convert %s to numeric' % str(x)) return x # NA-friendly array comparisons diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index 8c5764a3f59a6..740e3d0821cd7 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -14,6 +14,7 @@ import pandas.core.common as com import pandas.util.testing as tm import pandas.core.config as cf +from pandas.core import nanops _multiprocess_can_split_ = True @@ -311,6 +312,54 @@ def test_ensure_int32(): assert(result.dtype == np.int32) +class TestEnsureNumeric(unittest.TestCase): + def test_numeric_values(self): + # Test integer + self.assertEqual(nanops._ensure_numeric(1), 1, 'Failed for int') + # Test float + self.assertEqual(nanops._ensure_numeric(1.1), 1.1, 'Failed for float') + # Test complex + self.assertEqual(nanops._ensure_numeric(1 + 2j), 1 + 2j, + 'Failed for complex') + + def test_ndarray(self): + # Test numeric ndarray + values = np.array([1, 2, 3]) + self.assertTrue(np.allclose(nanops._ensure_numeric(values), values), + 'Failed for numeric ndarray') + + # Test object ndarray + o_values = values.astype(object) + self.assertTrue(np.allclose(nanops._ensure_numeric(o_values), values), + 'Failed for object ndarray') + + # Test convertible string ndarray + s_values = np.array(['1', '2', '3'], dtype=object) + self.assertTrue(np.allclose(nanops._ensure_numeric(s_values), values), + 'Failed for convertible string ndarray') + + # Test non-convertible string ndarray + s_values = np.array(['foo', 'bar', 'baz'], dtype=object) + self.assertRaises(ValueError, + lambda: nanops._ensure_numeric(s_values)) + + def test_convertable_values(self): + self.assertTrue(np.allclose(nanops._ensure_numeric('1'), 1.0), + 'Failed for convertible integer string') + self.assertTrue(np.allclose(nanops._ensure_numeric('1.1'), 1.1), + 'Failed for convertible float string') + self.assertTrue(np.allclose(nanops._ensure_numeric('1+1j'), 1 + 1j), + 'Failed for convertible complex string') + + def test_non_convertable_values(self): + self.assertRaises(TypeError, + lambda: nanops._ensure_numeric('foo')) + self.assertRaises(TypeError, + lambda: nanops._ensure_numeric({})) + self.assertRaises(TypeError, + lambda: nanops._ensure_numeric([])) + + def test_ensure_platform_int(): # verify that when we create certain types of indices