Skip to content

Commit 5fdf296

Browse files
committed
GH #14499 Panel.ffill ignores axis parameter and fill along axis=1
1 parent 3e4f839 commit 5fdf296

File tree

3 files changed

+79
-19
lines changed

3 files changed

+79
-19
lines changed

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,4 @@ Bug Fixes
300300
- Bug in ``Series.unique()`` in which unsigned 64-bit integers were causing overflow (:issue:`14721`)
301301
- Require at least 0.23 version of cython to avoid problems with character encodings (:issue:`14699`)
302302
- Bug in converting object elements of array-like objects to unsigned 64-bit integers (:issue:`4471`)
303+
- Bug in ``pd.Panel.ffill`` where ``axis`` was not propagated (:issue:`14499`)

pandas/core/generic.py

+34-19
Original file line numberDiff line numberDiff line change
@@ -3262,26 +3262,21 @@ def fillna(self, value=None, method=None, axis=None, inplace=False,
32623262
'you passed a "{0}"'.format(type(value).__name__))
32633263
self._consolidate_inplace()
32643264

3265-
# set the default here, so functions examining the signaure
3265+
# set the default here, so functions examining the signature
32663266
# can detect if something was set (e.g. in groupby) (GH9221)
32673267
if axis is None:
3268-
axis = 0
3268+
if self.ndim == 3:
3269+
axis = 1
3270+
else:
3271+
axis = 0
3272+
32693273
axis = self._get_axis_number(axis)
32703274
method = missing.clean_fill_method(method)
32713275

32723276
from pandas import DataFrame
32733277
if value is None:
32743278
if method is None:
32753279
raise ValueError('must specify a fill method or value')
3276-
if self._is_mixed_type and axis == 1:
3277-
if inplace:
3278-
raise NotImplementedError()
3279-
result = self.T.fillna(method=method, limit=limit).T
3280-
3281-
# need to downcast here because of all of the transposes
3282-
result._data = result._data.downcast()
3283-
3284-
return result
32853280

32863281
# > 3d
32873282
if self.ndim > 3:
@@ -3290,21 +3285,41 @@ def fillna(self, value=None, method=None, axis=None, inplace=False,
32903285

32913286
# 3d
32923287
elif self.ndim == 3:
3293-
32943288
# fill in 2d chunks
3295-
result = dict([(col, s.fillna(method=method, value=value))
3296-
for col, s in self.iteritems()])
3289+
if axis == 0:
3290+
frame = self.swapaxes(0, 1)
3291+
axis2d = 0
3292+
else:
3293+
frame = self
3294+
axis2d = axis - 1
3295+
result = dict([(col, s.fillna(method=method,
3296+
value=value,
3297+
axis=axis2d))
3298+
for col, s in frame.iteritems()])
32973299
new_obj = self._constructor.\
32983300
from_dict(result).__finalize__(self)
3301+
if axis == 0:
3302+
new_obj = new_obj.swapaxes(0, 1)
32993303
new_data = new_obj._data
33003304

33013305
else:
33023306
# 2d or less
3303-
method = missing.clean_fill_method(method)
3304-
new_data = self._data.interpolate(method=method, axis=axis,
3305-
limit=limit, inplace=inplace,
3306-
coerce=True,
3307-
downcast=downcast)
3307+
if self._is_mixed_type and axis == 1:
3308+
if inplace:
3309+
raise NotImplementedError()
3310+
result = self.T.fillna(method=method, limit=limit).T
3311+
3312+
# need to downcast here because of all of the transposes
3313+
result._data = result._data.downcast()
3314+
3315+
return result
3316+
else:
3317+
method = missing.clean_fill_method(method)
3318+
new_data = self._data.interpolate(method=method, axis=axis,
3319+
limit=limit,
3320+
inplace=inplace,
3321+
coerce=True,
3322+
downcast=downcast)
33083323
else:
33093324
if method is not None:
33103325
raise ValueError('cannot specify both a fill method and value')

pandas/tests/test_panel.py

+44
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,50 @@ def test_ffill_bfill(self):
15191519
assert_panel_equal(self.panel.bfill(),
15201520
self.panel.fillna(method='bfill'))
15211521

1522+
def test_ffill_bfill_axis(self):
1523+
# GH 14499
1524+
a = Panel({
1525+
'a': np.arange(15, dtype=float).reshape((5, 3)),
1526+
'b': np.arange(15, 30, dtype=float).reshape((5, 3))
1527+
})
1528+
f0 = a.copy()
1529+
f1 = a.copy()
1530+
f2 = a.copy()
1531+
b0 = a.copy()
1532+
b1 = a.copy()
1533+
b2 = a.copy()
1534+
a['a'].loc[1, 1] = np.nan
1535+
f0['a'].loc[1, 1] = np.nan
1536+
f1['a'].loc[1, 1] = 1
1537+
f2['a'].loc[1, 1] = 3
1538+
b0['a'].loc[1, 1] = 19.0
1539+
b1['a'].loc[1, 1] = 7
1540+
b2['a'].loc[1, 1] = 5
1541+
1542+
# method='ffill'
1543+
# axis=0
1544+
assert_panel_equal(a.ffill(axis=0), f0)
1545+
1546+
# method='ffill'
1547+
# axis=1
1548+
assert_panel_equal(a.ffill(axis=1), f1)
1549+
1550+
# method='ffill'
1551+
# axis=2
1552+
assert_panel_equal(a.ffill(axis=2), f2)
1553+
1554+
# method='bfill'
1555+
# axis=1
1556+
assert_panel_equal(a.bfill(axis=0), b0)
1557+
1558+
# method='bfill'
1559+
# axis=1
1560+
assert_panel_equal(a.bfill(axis=1), b1)
1561+
1562+
# method='bfill'
1563+
# axis=2
1564+
assert_panel_equal(a.bfill(axis=2), b2)
1565+
15221566
def test_truncate_fillna_bug(self):
15231567
# #1823
15241568
result = self.panel.truncate(before=None, after=None, axis='items')

0 commit comments

Comments
 (0)