Skip to content

BUG: Bug in fillna with limit and value specified #6628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 13, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ Bug Fixes
- Bug in sql writing with mixed dtypes possibly leading to data loss (:issue:`6509`)
- Bug in popping from a Series (:issue:`6600`)
- Bug in ``iloc`` indexing when positional indexer matched Int64Index of corresponding axis no reordering happened (:issue:`6612`)

- Bug in ``fillna`` with ``limit`` and ``value`` specified

pandas 0.13.1
-------------
Expand Down
10 changes: 7 additions & 3 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2162,7 +2162,9 @@ def fillna(self, value=None, method=None, axis=0, inplace=False,
from pandas import Series
value = Series(value)

new_data = self._data.fillna(value=value, inplace=inplace,
new_data = self._data.fillna(value=value,
limit=limit,
inplace=inplace,
downcast=downcast)

elif isinstance(value, (dict, com.ABCSeries)):
Expand All @@ -2176,10 +2178,12 @@ def fillna(self, value=None, method=None, axis=0, inplace=False,
if k not in result:
continue
obj = result[k]
obj.fillna(v, inplace=True)
obj.fillna(v, limit=limit, inplace=True)
return result
else:
new_data = self._data.fillna(value=value, inplace=inplace,
new_data = self._data.fillna(value=value,
limit=limit,
inplace=inplace,
downcast=downcast)

if inplace:
Expand Down
20 changes: 17 additions & 3 deletions pandas/core/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,14 +367,19 @@ def apply(self, func, **kwargs):
""" apply the function to my values; return a block if we are not one """
return self.as_block(func(self.values))

def fillna(self, value, inplace=False, downcast=None):
def fillna(self, value, limit=None, inplace=False, downcast=None):
if not self._can_hold_na:
if inplace:
return [self]
else:
return [self.copy()]

mask = com.isnull(self.values)
if limit is not None:
if self.ndim > 2:
raise NotImplementedError
mask[mask.cumsum(self.ndim-1)>limit]=False

value = self._try_fill(value)
blocks = self.putmask(mask, value, inplace=inplace)
return self._maybe_downcast(blocks, downcast)
Expand Down Expand Up @@ -1680,11 +1685,18 @@ def _try_fill(self, value):
value = tslib.iNaT
return value

def fillna(self, value, inplace=False, downcast=None):
def fillna(self, value, limit=None,
inplace=False, downcast=None):

# straight putmask here
values = self.values if inplace else self.values.copy()
mask = com.isnull(self.values)
value = self._try_fill(value)
if limit is not None:
if self.ndim > 2:
raise NotImplementedError
mask[mask.cumsum(self.ndim-1)>limit]=False

np.putmask(values, mask, value)
return [self if inplace else
make_block(values, self.items, self.ref_items, fastpath=True)]
Expand Down Expand Up @@ -1889,8 +1901,10 @@ def interpolate(self, method='pad', axis=0, inplace=False,
self.values.to_dense(), method, axis, limit, fill_value)
return self.make_block(values, self.items, self.ref_items)

def fillna(self, value, inplace=False, downcast=None):
def fillna(self, value, limit=None, inplace=False, downcast=None):
# we may need to upcast our fill to match our dtype
if limit is not None:
raise NotImplementedError
if issubclass(self.dtype.type, np.floating):
value = float(value)
values = self.values if inplace else self.values.copy()
Expand Down
11 changes: 11 additions & 0 deletions pandas/tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -7113,6 +7113,17 @@ def test_fillna(self):
df.fillna({ 2: 'foo' }, inplace=True)
assert_frame_equal(df, expected)

# limit and value
df = DataFrame(np.random.randn(10,3))
df.iloc[2:7,0] = np.nan
df.iloc[3:5,2] = np.nan

expected = df.copy()
expected.iloc[2,0] = 999
expected.iloc[3,2] = 999
result = df.fillna(999,limit=1)
assert_frame_equal(result, expected)

def test_fillna_dtype_conversion(self):
# make sure that fillna on an empty frame works
df = DataFrame(index=["A","B","C"], columns = [1,2,3,4,5])
Expand Down
5 changes: 5 additions & 0 deletions pandas/tests/test_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,11 @@ def test_fillna(self):
self.assertRaises(TypeError, self.panel.fillna, [1, 2])
self.assertRaises(TypeError, self.panel.fillna, (1, 2))

# limit not implemented when only value is specified
p = Panel(np.random.randn(3,4,5))
p.iloc[0:2,0:2,0:2] = np.nan
self.assertRaises(NotImplementedError, lambda : p.fillna(999,limit=1))

def test_ffill_bfill(self):
assert_panel_equal(self.panel.ffill(),
self.panel.fillna(method='ffill'))
Expand Down
10 changes: 10 additions & 0 deletions pandas/tests/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2941,6 +2941,16 @@ def test_fillna(self):
expected = Series([0,0,2.], list('bac'))
assert_series_equal(result,expected)

# limit
s = Series(np.nan,index=[0,1,2])
result = s.fillna(999,limit=1)
expected = Series([999,np.nan,np.nan],index=[0,1,2])
assert_series_equal(result,expected)

result = s.fillna(999,limit=2)
expected = Series([999,999,np.nan],index=[0,1,2])
assert_series_equal(result,expected)

def test_fillna_bug(self):
x = Series([nan, 1., nan, 3., nan], ['z', 'a', 'b', 'c', 'd'])
filled = x.fillna(method='ffill')
Expand Down