@@ -626,9 +626,29 @@ def test_arith_flex_frame_corner(self, float_frame):
626626 expected = float_frame .sort_index () * np .nan
627627 tm .assert_frame_equal (result , expected )
628628
629- res = float_frame .add (float_frame .iloc [0 ], fill_value = 3 )
629+ @pytest .mark .parametrize ("axis" , [0 , 1 ])
630+ def test_arith_flex_frame_fill_value_corner (self , float_frame , axis ):
631+ rng = np .random .default_rng (60 )
632+ mask = rng .random (float_frame .shape ) < 0.2
633+ left = float_frame .mask (mask )
634+ right = left .iloc [0 ].value
630635
631- res = float_frame .add (float_frame .iloc [0 ], axis = "index" , fill_value = 3 )
636+ result = left .add (right , axis = axis , fill_value = 3 )
637+
638+ if axis == 0 : # axis = index, vertical
639+ expected = result * np .nan
640+
641+ else : # axis = columns, horizontal
642+ right_df = DataFrame ([right ] * result .shape [0 ], index = result .index )
643+ left_filled = left .fillna (3 )
644+ right_filled = right_df .fillna (3 )
645+ expected = right_filled + left_filled
646+ expected = expected .mask (expected == 6 , pd .NA )
647+
648+ print (result )
649+ print (expected )
650+
651+ tm .assert_frame_equal (result , expected )
632652
633653 @pytest .mark .parametrize ("op" , ["add" , "sub" , "mul" , "mod" ])
634654 def test_arith_flex_series_ops (self , simple_frame , op ):
@@ -2190,3 +2210,61 @@ def test_mixed_col_index_dtype(string_dtype_no_object):
21902210 expected .columns = expected .columns .astype (string_dtype_no_object )
21912211
21922212 tm .assert_frame_equal (result , expected )
2213+
2214+
2215+ dt_params = [
2216+ (tm .ALL_INT_NUMPY_DTYPES [0 ], 5 ),
2217+ (tm .ALL_INT_EA_DTYPES [0 ], 5 ),
2218+ (tm .FLOAT_NUMPY_DTYPES [0 ], 4.9 ),
2219+ (tm .FLOAT_EA_DTYPES [0 ], 4.9 ),
2220+ ]
2221+
2222+ axes = [0 , 1 ]
2223+
2224+
2225+ @pytest .mark .parametrize (
2226+ "data_type,fill_val, axis" ,
2227+ [(dt , val , axis ) for axis in axes for dt , val in dt_params ],
2228+ )
2229+ def test_df_fill_value_dtype (data_type , fill_val , axis ):
2230+ # GH 61581
2231+ base_data = np .arange (25 ).reshape (5 , 5 )
2232+ mult_list = [1 , np .nan , 5 , np .nan , 3 ]
2233+ np_int_flag = 0
2234+
2235+ try :
2236+ mult_data = pd .array (mult_list , dtype = data_type )
2237+ except ValueError as e :
2238+ # Numpy int type cannot represent NaN, it will end up here
2239+ if "cannot convert float NaN to integer" in str (e ):
2240+ mult_data = np .asarray (mult_list )
2241+ np_int_flag = 1
2242+
2243+ columns = list ("ABCDE" )
2244+ df = DataFrame (base_data , columns = columns )
2245+
2246+ for i in range (df .shape [0 ]):
2247+ try :
2248+ df .iat [i , i ] = np .nan
2249+ df .iat [i + 1 , i ] = pd .NA
2250+ df .iat [i + 3 , i ] = pd .NA
2251+ except IndexError :
2252+ pass
2253+
2254+ mult_mat = np .broadcast_to (mult_data , df .shape )
2255+ if axis == 0 :
2256+ mask = np .isnan (mult_mat ).T
2257+ else :
2258+ mask = np .isnan (mult_mat )
2259+ mask = df .isna ().values & mask
2260+
2261+ df_result = df .mul (mult_data , axis = axis , fill_value = fill_val )
2262+ if np_int_flag == 1 :
2263+ mult_np = np .nan_to_num (mult_data , nan = fill_val )
2264+ df_expected = (df .fillna (fill_val ).mul (mult_np , axis = axis )).mask (mask , np .nan )
2265+ else :
2266+ df_expected = (
2267+ df .fillna (fill_val ).mul (mult_data .fillna (fill_val ), axis = axis )
2268+ ).mask (mask , np .nan )
2269+
2270+ tm .assert_frame_equal (df_result , df_expected )
0 commit comments