@@ -58,6 +58,17 @@ def adjust_negative_zero(zero, expected):
58
58
return expected
59
59
60
60
61
+ def compare_op (series , other , op ):
62
+ left = np .abs (series ) if op in (ops .rpow , operator .pow ) else series
63
+ right = np .abs (other ) if op in (ops .rpow , operator .pow ) else other
64
+
65
+ cython_or_numpy = op (left , right )
66
+ python = left .combine (right , op )
67
+ if isinstance (other , Series ) and not other .index .equals (series .index ):
68
+ python .index = python .index ._with_freq (None )
69
+ tm .assert_series_equal (cython_or_numpy , python )
70
+
71
+
61
72
# TODO: remove this kludge once mypy stops giving false positives here
62
73
# List comprehension has incompatible type List[PandasObject]; expected List[RangeIndex]
63
74
# See GH#29725
@@ -959,77 +970,54 @@ def test_frame_operators(self, float_frame):
959
970
assert (df + df ).equals (df )
960
971
tm .assert_frame_equal (df + df , df )
961
972
962
- # TODO: taken from tests.series.test_operators; needs cleanup
963
- def test_series_operators (self ):
964
- def _check_op (series , other , op , pos_only = False ):
965
- left = np .abs (series ) if pos_only else series
966
- right = np .abs (other ) if pos_only else other
967
-
968
- cython_or_numpy = op (left , right )
969
- python = left .combine (right , op )
970
- if isinstance (other , Series ) and not other .index .equals (series .index ):
971
- python .index = python .index ._with_freq (None )
972
- tm .assert_series_equal (cython_or_numpy , python )
973
-
974
- def check (series , other ):
975
- simple_ops = ["add" , "sub" , "mul" , "truediv" , "floordiv" , "mod" ]
976
-
977
- for opname in simple_ops :
978
- _check_op (series , other , getattr (operator , opname ))
973
+ @pytest .mark .parametrize (
974
+ "func" ,
975
+ [lambda x : x * 2 , lambda x : x [::2 ], lambda x : 5 ],
976
+ ids = ["multiply" , "slice" , "constant" ],
977
+ )
978
+ def test_series_operators_arithmetic (self , all_arithmetic_functions , func ):
979
+ op = all_arithmetic_functions
980
+ series = tm .makeTimeSeries ().rename ("ts" )
981
+ other = func (series )
982
+ compare_op (series , other , op )
979
983
980
- _check_op (series , other , operator .pow , pos_only = True )
984
+ @pytest .mark .parametrize (
985
+ "func" , [lambda x : x + 1 , lambda x : 5 ], ids = ["add" , "constant" ]
986
+ )
987
+ def test_series_operators_compare (self , comparison_op , func ):
988
+ op = comparison_op
989
+ series = tm .makeTimeSeries ().rename ("ts" )
990
+ other = func (series )
991
+ compare_op (series , other , op )
981
992
982
- _check_op (series , other , ops .radd )
983
- _check_op (series , other , ops .rsub )
984
- _check_op (series , other , ops .rtruediv )
985
- _check_op (series , other , ops .rfloordiv )
986
- _check_op (series , other , ops .rmul )
987
- _check_op (series , other , ops .rpow , pos_only = True )
988
- _check_op (series , other , ops .rmod )
993
+ @pytest .mark .parametrize (
994
+ "func" ,
995
+ [lambda x : x * 2 , lambda x : x [::2 ], lambda x : 5 ],
996
+ ids = ["multiply" , "slice" , "constant" ],
997
+ )
998
+ def test_divmod (self , func ):
999
+ series = tm .makeTimeSeries ().rename ("ts" )
1000
+ other = func (series )
1001
+ results = divmod (series , other )
1002
+ if isinstance (other , abc .Iterable ) and len (series ) != len (other ):
1003
+ # if the lengths don't match, this is the test where we use
1004
+ # `tser[::2]`. Pad every other value in `other_np` with nan.
1005
+ other_np = []
1006
+ for n in other :
1007
+ other_np .append (n )
1008
+ other_np .append (np .nan )
1009
+ else :
1010
+ other_np = other
1011
+ other_np = np .asarray (other_np )
1012
+ with np .errstate (all = "ignore" ):
1013
+ expecteds = divmod (series .values , np .asarray (other_np ))
989
1014
990
- tser = tm .makeTimeSeries ().rename ("ts" )
991
- check (tser , tser * 2 )
992
- check (tser , tser [::2 ])
993
- check (tser , 5 )
994
-
995
- def check_comparators (series , other ):
996
- _check_op (series , other , operator .gt )
997
- _check_op (series , other , operator .ge )
998
- _check_op (series , other , operator .eq )
999
- _check_op (series , other , operator .lt )
1000
- _check_op (series , other , operator .le )
1001
-
1002
- check_comparators (tser , 5 )
1003
- check_comparators (tser , tser + 1 )
1004
-
1005
- # TODO: taken from tests.series.test_operators; needs cleanup
1006
- def test_divmod (self ):
1007
- def check (series , other ):
1008
- results = divmod (series , other )
1009
- if isinstance (other , abc .Iterable ) and len (series ) != len (other ):
1010
- # if the lengths don't match, this is the test where we use
1011
- # `tser[::2]`. Pad every other value in `other_np` with nan.
1012
- other_np = []
1013
- for n in other :
1014
- other_np .append (n )
1015
- other_np .append (np .nan )
1016
- else :
1017
- other_np = other
1018
- other_np = np .asarray (other_np )
1019
- with np .errstate (all = "ignore" ):
1020
- expecteds = divmod (series .values , np .asarray (other_np ))
1021
-
1022
- for result , expected in zip (results , expecteds ):
1023
- # check the values, name, and index separately
1024
- tm .assert_almost_equal (np .asarray (result ), expected )
1025
-
1026
- assert result .name == series .name
1027
- tm .assert_index_equal (result .index , series .index ._with_freq (None ))
1015
+ for result , expected in zip (results , expecteds ):
1016
+ # check the values, name, and index separately
1017
+ tm .assert_almost_equal (np .asarray (result ), expected )
1028
1018
1029
- tser = tm .makeTimeSeries ().rename ("ts" )
1030
- check (tser , tser * 2 )
1031
- check (tser , tser [::2 ])
1032
- check (tser , 5 )
1019
+ assert result .name == series .name
1020
+ tm .assert_index_equal (result .index , series .index ._with_freq (None ))
1033
1021
1034
1022
def test_series_divmod_zero (self ):
1035
1023
# Check that divmod uses pandas convention for division by zero,
0 commit comments