diff --git a/doc/source/whatsnew/v0.18.1.txt b/doc/source/whatsnew/v0.18.1.txt index cc84347313b42..cfbb2dfc75519 100644 --- a/doc/source/whatsnew/v0.18.1.txt +++ b/doc/source/whatsnew/v0.18.1.txt @@ -321,3 +321,5 @@ Bug Fixes - Bug where ``loffset`` argument was not applied when calling ``resample().count()`` on a timeseries (:issue:`12725`) - ``pd.read_excel()`` now accepts path objects (e.g. ``pathlib.Path``, ``py.path.local``) for the file path, in line with other ``read_*`` functions (:issue:`12655`) - ``pd.read_excel()`` now accepts column names associated with keyword argument ``names``(:issue `12870`) + +- Bug in ``fill_value`` is ignored if the argument to a binary operator is a constant (:issue `12723`) diff --git a/pandas/core/ops.py b/pandas/core/ops.py index cb0d06c1739b6..bced97b0fde47 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -933,6 +933,9 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0): return self._binop(self._constructor(other, self.index), op, level=level, fill_value=fill_value) else: + if fill_value is not None: + self = self.fillna(fill_value) + return self._constructor(op(self.values, other), self.index).__finalize__(self) @@ -1088,6 +1091,9 @@ def f(self, other, axis=default_axis, level=None, fill_value=None): raise ValueError("Incompatible argument shape: %s" % (other.shape, )) else: + if fill_value is not None: + self = self.fillna(fill_value) + return self._combine_const(other, na_op) f.__name__ = name diff --git a/pandas/sparse/tests/test_frame.py b/pandas/sparse/tests/test_frame.py index 90e98aff6028a..c179823a67a30 100644 --- a/pandas/sparse/tests/test_frame.py +++ b/pandas/sparse/tests/test_frame.py @@ -60,6 +60,15 @@ def setUp(self): self.empty = SparseDataFrame() + def test_fill_value_when_combine_const(self): + # GH12723 + dat = np.array([0, 1, np.nan, 3, 4, 5], dtype='float') + df = SparseDataFrame({'foo': dat}, index=range(6)) + + exp = df.fillna(0).add(2) + res = df.add(2, fill_value=0) + tm.assert_sp_frame_equal(res, exp) + def test_as_matrix(self): empty = self.empty.as_matrix() self.assertEqual(empty.shape, (0, 0)) diff --git a/pandas/sparse/tests/test_series.py b/pandas/sparse/tests/test_series.py index fe05108cb993c..ef0860f3bd980 100644 --- a/pandas/sparse/tests/test_series.py +++ b/pandas/sparse/tests/test_series.py @@ -740,6 +740,14 @@ def test_fill_value_corner(self): result = cop2 / cop self.assertTrue(np.isnan(result.fill_value)) + def test_fill_value_when_combine_const(self): + # GH12723 + s = SparseSeries([0, 1, np.nan, 3, 4, 5], index=np.arange(6)) + + exp = s.fillna(0).add(2) + res = s.add(2, fill_value=0) + self.assert_series_equal(res, exp) + def test_shift(self): series = SparseSeries([nan, 1., 2., 3., nan, nan], index=np.arange(6)) diff --git a/pandas/tests/frame/test_missing.py b/pandas/tests/frame/test_missing.py index fd212664b5b9b..0411fb4d96e82 100644 --- a/pandas/tests/frame/test_missing.py +++ b/pandas/tests/frame/test_missing.py @@ -425,3 +425,19 @@ def test_fill_corner(self): # TODO(wesm): unused? result = empty_float.fillna(value=0) # noqa + + def test_fill_value_when_combine_const(self): + # GH12723 + dat = np.array([0, 1, np.nan, 3, 4, 5], dtype='float') + df = DataFrame({'foo': dat}, index=range(6)) + + exp = df.fillna(0).add(2) + res = df.add(2, fill_value=0) + assert_frame_equal(res, exp) + + +if __name__ == '__main__': + import nose + nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], + # '--with-coverage', '--cover-package=pandas.core'] + exit=False) diff --git a/pandas/tests/series/test_missing.py b/pandas/tests/series/test_missing.py index 4bd77c01db9d0..302e05ef3ae8a 100644 --- a/pandas/tests/series/test_missing.py +++ b/pandas/tests/series/test_missing.py @@ -452,3 +452,18 @@ def test_dropna_preserve_name(self): ts = self.ts.copy() ts.dropna(inplace=True) self.assertEqual(ts.name, name) + + def test_fill_value_when_combine_const(self): + # GH12723 + s = Series([0, 1, np.nan, 3, 4, 5]) + + exp = s.fillna(0).add(2) + res = s.add(2, fill_value=0) + assert_series_equal(res, exp) + + +if __name__ == '__main__': + import nose + nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], + # '--with-coverage', '--cover-package=pandas.core'] + exit=False)