Skip to content

Commit bda3ab1

Browse files
committed
+tests (coerce tests for time dtypes still TODO), corrections
1 parent 9f9e442 commit bda3ab1

File tree

2 files changed

+211
-8
lines changed

2 files changed

+211
-8
lines changed

pandas/core/generic.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -3446,14 +3446,18 @@ def fillna(self, value=None, method=None, axis=None, inplace=False,
34463446
limit=None, downcast=None, errors=None):
34473447
inplace = validate_bool_kwarg(inplace, 'inplace')
34483448

3449-
try:
3450-
missing.validate_fill_value(self, value)
3451-
except TypeError:
3452-
if errors == 'ignore':
3453-
return
3454-
elif errors == 'raise':
3455-
raise
3456-
# if errors == 'coerce' continue
3449+
if value:
3450+
# fill values by column, not all at once, to respect dtypes.
3451+
if not isinstance(value, dict) and isinstance(self, ABCDataFrame):
3452+
value = {col: value for col in self.columns}
3453+
try:
3454+
missing.validate_fill_value(self, value)
3455+
except TypeError:
3456+
if errors == 'ignore':
3457+
return self
3458+
elif errors == 'raise':
3459+
raise
3460+
# if errors == 'coerce' continue
34573461

34583462
if isinstance(value, (list, tuple)):
34593463
raise TypeError('"value" parameter must be a scalar or dict, but '

pandas/tests/frame/test_missing.py

+199
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,205 @@ def test_fill_value_when_combine_const(self):
519519
res = df.add(2, fill_value=0)
520520
assert_frame_equal(res, exp)
521521

522+
def test_fillna_error_modes_numeric_fill(self):
523+
# Filling numeric/object cols with a numeric
524+
df1 = DataFrame({'a': [nan, 1.0],
525+
'b': [nan, True],
526+
'c': [nan, 1],
527+
'd': [nan, 1j],
528+
'e': [nan, 'foo'],})
529+
expected = DataFrame({'a': [0.0, 1.0],
530+
'b': [0, True],
531+
'c': [0.0, 1.0],
532+
'd': [0, 1j],
533+
'e': [0, 'foo']})
534+
535+
result = df1.fillna(0, errors='coerce')
536+
assert_frame_equal(result, expected)
537+
result = df1.fillna(0, errors='ignore')
538+
assert_frame_equal(result, expected)
539+
result = df1.fillna(0, errors='raise')
540+
assert_frame_equal(result, expected)
541+
542+
def test_fillna_error_modes_bool_fill(self):
543+
# Filling numeric/object cols with a bool
544+
df1 = DataFrame({'a': [nan, 1.0],
545+
'b': [nan, True],
546+
'c': [nan, 1],
547+
'd': [nan, 1j],
548+
'e': [nan, 'foo']})
549+
550+
result = df1.fillna(False, errors='coerce')
551+
expected = DataFrame({'a': [0.0, 1.0],
552+
'b': [False, True],
553+
'c': [0.0, 1.0],
554+
'd': [0.0, 1j],
555+
'e': [False, 'foo']})
556+
assert_frame_equal(result, expected)
557+
558+
result = df1.fillna(False, errors='ignore')
559+
expected = DataFrame({'a': [nan, 1.0],
560+
'b': [False, True],
561+
'c': [nan, 1.0],
562+
'd': [nan, 1j],
563+
'e': [False, 'foo']})
564+
assert_frame_equal(result, expected)
565+
566+
with tm.assertRaises(TypeError):
567+
df1.fillna(False, errors='raise')
568+
569+
def test_fillna_error_modes_obj_fill(self):
570+
# Filling numeric/object cols with an obj
571+
df1 = DataFrame({'a': [nan, 1.0],
572+
'b': [nan, True],
573+
'c': [nan, 1],
574+
'd': [nan, 1j],
575+
'e': [nan, 'foo']})
576+
577+
result = df1.fillna('bar', errors='coerce')
578+
expected = DataFrame({'a': ['bar', 1.0],
579+
'b': ['bar', True],
580+
'c': ['bar', 1.0],
581+
'd': ['bar', 1j],
582+
'e': ['bar', 'foo']})
583+
assert_frame_equal(result, expected)
584+
585+
result = df1.fillna('bar', errors='ignore')
586+
expected = DataFrame({'a': [nan, 1.0],
587+
'b': ['bar', True], # col cast to obj!
588+
'c': [nan, 1.0],
589+
'd': [nan, 1j],
590+
'e': ['bar', 'foo']})
591+
assert_frame_equal(result, expected)
592+
593+
with tm.assertRaises(TypeError):
594+
df1.fillna('bar', errors='raise')
595+
596+
def test_fillna_error_modes_datetime_fill(self):
597+
# Filling numeric/object/datetime cols with a datetime
598+
timestamp = Timestamp('1970-01-01')
599+
600+
df1 = DataFrame({'a': [nan, 1.0],
601+
'b': [nan, True],
602+
'c': [nan, 1],
603+
'd': [nan, 1j],
604+
'e': [nan, 'foo'],
605+
'f': [nan, timestamp]})
606+
607+
result = df1.fillna(Timestamp('1970-01-01'), errors='coerce')
608+
expected = DataFrame({'a': [timestamp, 1.0],
609+
'b': [timestamp, True],
610+
'c': [timestamp, 1.0],
611+
'd': [timestamp, 1j],
612+
'e': [timestamp, 'foo'],
613+
'f': [timestamp, timestamp]})
614+
assert_frame_equal(result, expected)
615+
616+
result = df1.fillna(timestamp, errors='ignore')
617+
expected = DataFrame({'a': [nan, 1.0],
618+
'b': [timestamp, True], # col cast to obj!
619+
'c': [nan, 1.0],
620+
'd': [nan, 1j],
621+
'e': [timestamp, 'foo'],
622+
'f': [timestamp, timestamp]})
623+
assert_frame_equal(result, expected)
624+
625+
with tm.assertRaises(TypeError):
626+
df1.fillna(Timestamp('1970-01-01'), errors='raise')
627+
628+
def test_fillna_error_modes_timedelta_fill(self):
629+
# Filling numeric/object/timedelta cols with a timedelta
630+
timedelta = pd.Timedelta('1 hour')
631+
632+
df1 = DataFrame({'a': [nan, 1.0],
633+
'b': [nan, True],
634+
'c': [nan, 1],
635+
'd': [nan, 1j],
636+
'e': [nan, 'foo'],
637+
'f': [nan, timedelta]})
638+
639+
result = df1.fillna(timedelta, errors='coerce')
640+
expected = DataFrame({'a': [timedelta, 1.0],
641+
'b': [timedelta, True],
642+
'c': [timedelta, 1.0],
643+
'd': [timedelta, 1j],
644+
'e': [timedelta, 'foo'],
645+
'f': [timedelta, timedelta]})
646+
assert_frame_equal(result, expected)
647+
648+
result = df1.fillna(pd.Timedelta('1 hour'), errors='ignore')
649+
expected = DataFrame({'a': [nan, 1.0],
650+
'b': [pd.Timedelta('1 hour'), True], # col cast to obj!
651+
'c': [nan, 1.0],
652+
'd': [nan, 1j],
653+
'e': [pd.Timedelta('1 hour'), 'foo'],
654+
'f': [pd.Timedelta('1 hour'), pd.Timedelta('1 hour')]})
655+
assert_frame_equal(result, expected)
656+
657+
with tm.assertRaises(TypeError):
658+
df1.fillna(Timestamp('1970-01-01'), errors='raise')
659+
660+
def test_fillna_error_modes_period_fill(self):
661+
# Filling numeric/object/period cols with a period
662+
period = pd.Period('1 hour')
663+
664+
df1 = DataFrame({'a': [nan, 1.0],
665+
'b': [nan, True],
666+
'c': [nan, 1],
667+
'd': [nan, 1j],
668+
'e': [nan, 'foo'],
669+
'f': [nan, period]})
670+
671+
result = df1.fillna(pd.Period('1 hour'), errors='coerce')
672+
expected = DataFrame({'a': [period, 1.0],
673+
'b': [period, True],
674+
'c': [period, 1.0],
675+
'd': [period, 1j],
676+
'e': [period, 'foo'],
677+
'f': [period, period]})
678+
assert_frame_equal(result, expected)
679+
680+
result = df1.fillna(period, errors='ignore')
681+
expected = DataFrame({'a': [nan, 1.0],
682+
'b': [period, True], # col cast to obj!
683+
'c': [nan, 1.0],
684+
'd': [nan, 1j],
685+
'e': [period, 'foo'],
686+
'f': [period, period]})
687+
assert_frame_equal(result, expected)
688+
689+
with tm.assertRaises(TypeError):
690+
df1.fillna(period, errors='raise')
691+
692+
def test_fillna_error_modes_time_dtype_interactions(self):
693+
timedelta = pd.Timedelta('1 hour')
694+
period = pd.Period('1 hour')
695+
timestamp = Timestamp('1970-01-01')
696+
697+
df1 = DataFrame({'a': [nan, timedelta],
698+
'b': [nan, period],
699+
'c': [nan, timestamp]})
700+
701+
result = df1.fillna(timedelta, errors='ignore')
702+
expected = DataFrame({'a': [timedelta, timedelta],
703+
'b': [timedelta, period], # col cast to obj!
704+
'c': [nan, timestamp]})
705+
assert_frame_equal(result, expected)
706+
707+
result = df1.fillna(period, errors='ignore')
708+
expected = DataFrame({'a': [nan, timedelta],
709+
'b': [period, period], # col cast to obj!
710+
'c': [nan, timestamp]})
711+
assert_frame_equal(result, expected)
712+
713+
result = df1.fillna(timestamp, errors='ignore')
714+
expected = DataFrame({'a': [nan, timedelta],
715+
'b': [timestamp, period], # col cast to obj!
716+
'c': [timestamp, timestamp]})
717+
assert_frame_equal(result, expected)
718+
719+
# TODO: coerce tests.
720+
522721

523722
class TestDataFrameInterpolate(tm.TestCase, TestData):
524723

0 commit comments

Comments
 (0)