1
1
#!/usr/bin/env python
2
2
3
+ import warnings
4
+ import operator
3
5
from itertools import product
4
6
from distutils .version import LooseVersion
5
7
28
30
from pandas .util .testing import (assert_frame_equal , randbool ,
29
31
assertRaisesRegexp ,
30
32
assert_produces_warning , assert_series_equal )
31
- from pandas .compat import PY3 , u
33
+ from pandas .compat import PY3 , u , reduce
32
34
33
35
_series_frame_incompatible = _bool_ops_syms
34
36
_scalar_skip = 'in' , 'not in'
@@ -699,6 +701,16 @@ def check_chained_cmp_op(self, lhs, cmp1, mid, cmp2, rhs):
699
701
#-------------------------------------
700
702
# basic and complex alignment
701
703
704
+ def _is_datetime (x ):
705
+ return issubclass (x .dtype .type , np .datetime64 )
706
+
707
+
708
+ def should_warn (* args ):
709
+ not_mono = not any (map (operator .attrgetter ('is_monotonic' ), args ))
710
+ only_one_dt = reduce (operator .xor , map (_is_datetime , args ))
711
+ return not_mono and only_one_dt
712
+
713
+
702
714
class TestAlignment (object ):
703
715
704
716
index_types = 'i' , 'u' , 'dt'
@@ -719,13 +731,20 @@ def check_basic_frame_alignment(self, engine, parser):
719
731
tm .skip_if_no_ne (engine )
720
732
args = product (self .lhs_index_types , self .index_types ,
721
733
self .index_types )
722
- for lr_idx_type , rr_idx_type , c_idx_type in args :
723
- df = mkdf (10 , 10 , data_gen_f = f , r_idx_type = lr_idx_type ,
724
- c_idx_type = c_idx_type )
725
- df2 = mkdf (20 , 10 , data_gen_f = f , r_idx_type = rr_idx_type ,
726
- c_idx_type = c_idx_type )
727
- res = pd .eval ('df + df2' , engine = engine , parser = parser )
728
- assert_frame_equal (res , df + df2 )
734
+ with warnings .catch_warnings (record = True ):
735
+ warnings .simplefilter ('always' , RuntimeWarning )
736
+ for lr_idx_type , rr_idx_type , c_idx_type in args :
737
+ df = mkdf (10 , 10 , data_gen_f = f , r_idx_type = lr_idx_type ,
738
+ c_idx_type = c_idx_type )
739
+ df2 = mkdf (20 , 10 , data_gen_f = f , r_idx_type = rr_idx_type ,
740
+ c_idx_type = c_idx_type )
741
+ # only warns if not monotonic and not sortable
742
+ if should_warn (df .index , df2 .index ):
743
+ with tm .assert_produces_warning (RuntimeWarning ):
744
+ res = pd .eval ('df + df2' , engine = engine , parser = parser )
745
+ else :
746
+ res = pd .eval ('df + df2' , engine = engine , parser = parser )
747
+ assert_frame_equal (res , df + df2 )
729
748
730
749
def test_basic_frame_alignment (self ):
731
750
for engine , parser in ENGINES_PARSERS :
@@ -754,12 +773,20 @@ def check_medium_complex_frame_alignment(self, engine, parser):
754
773
args = product (self .lhs_index_types , self .index_types ,
755
774
self .index_types , self .index_types )
756
775
757
- for r1 , c1 , r2 , c2 in args :
758
- df = mkdf (3 , 2 , data_gen_f = f , r_idx_type = r1 , c_idx_type = c1 )
759
- df2 = mkdf (4 , 2 , data_gen_f = f , r_idx_type = r2 , c_idx_type = c2 )
760
- df3 = mkdf (5 , 2 , data_gen_f = f , r_idx_type = r2 , c_idx_type = c2 )
761
- res = pd .eval ('df + df2 + df3' , engine = engine , parser = parser )
762
- assert_frame_equal (res , df + df2 + df3 )
776
+ with warnings .catch_warnings (record = True ):
777
+ warnings .simplefilter ('always' , RuntimeWarning )
778
+
779
+ for r1 , c1 , r2 , c2 in args :
780
+ df = mkdf (3 , 2 , data_gen_f = f , r_idx_type = r1 , c_idx_type = c1 )
781
+ df2 = mkdf (4 , 2 , data_gen_f = f , r_idx_type = r2 , c_idx_type = c2 )
782
+ df3 = mkdf (5 , 2 , data_gen_f = f , r_idx_type = r2 , c_idx_type = c2 )
783
+ if should_warn (df .index , df2 .index , df3 .index ):
784
+ with tm .assert_produces_warning (RuntimeWarning ):
785
+ res = pd .eval ('df + df2 + df3' , engine = engine ,
786
+ parser = parser )
787
+ else :
788
+ res = pd .eval ('df + df2 + df3' , engine = engine , parser = parser )
789
+ assert_frame_equal (res , df + df2 + df3 )
763
790
764
791
@slow
765
792
def test_medium_complex_frame_alignment (self ):
@@ -775,20 +802,24 @@ def testit(r_idx_type, c_idx_type, index_name):
775
802
index = getattr (df , index_name )
776
803
s = Series (np .random .randn (5 ), index [:5 ])
777
804
778
- res = pd .eval ('df + s' , engine = engine , parser = parser )
805
+ if should_warn (df .index , s .index ):
806
+ with tm .assert_produces_warning (RuntimeWarning ):
807
+ res = pd .eval ('df + s' , engine = engine , parser = parser )
808
+ else :
809
+ res = pd .eval ('df + s' , engine = engine , parser = parser )
810
+
779
811
if r_idx_type == 'dt' or c_idx_type == 'dt' :
780
- if engine == 'numexpr' :
781
- expected = df .add (s )
782
- else :
783
- expected = df + s
812
+ expected = df .add (s ) if engine == 'numexpr' else df + s
784
813
else :
785
814
expected = df + s
786
815
assert_frame_equal (res , expected )
787
816
788
817
args = product (self .lhs_index_types , self .index_types ,
789
818
('index' , 'columns' ))
790
- for r_idx_type , c_idx_type , index_name in args :
791
- testit (r_idx_type , c_idx_type , index_name )
819
+ with warnings .catch_warnings (record = True ):
820
+ warnings .simplefilter ('always' , RuntimeWarning )
821
+ for r_idx_type , c_idx_type , index_name in args :
822
+ testit (r_idx_type , c_idx_type , index_name )
792
823
793
824
def test_basic_frame_series_alignment (self ):
794
825
for engine , parser in ENGINES_PARSERS :
@@ -802,13 +833,14 @@ def testit(r_idx_type, c_idx_type, index_name):
802
833
c_idx_type = c_idx_type )
803
834
index = getattr (df , index_name )
804
835
s = Series (np .random .randn (5 ), index [:5 ])
836
+ if should_warn (s .index , df .index ):
837
+ with tm .assert_produces_warning (RuntimeWarning ):
838
+ res = pd .eval ('s + df' , engine = engine , parser = parser )
839
+ else :
840
+ res = pd .eval ('s + df' , engine = engine , parser = parser )
805
841
806
- res = pd .eval ('s + df' , engine = engine , parser = parser )
807
842
if r_idx_type == 'dt' or c_idx_type == 'dt' :
808
- if engine == 'numexpr' :
809
- expected = df .add (s )
810
- else :
811
- expected = s + df
843
+ expected = df .add (s ) if engine == 'numexpr' else s + df
812
844
else :
813
845
expected = s + df
814
846
assert_frame_equal (res , expected )
@@ -820,8 +852,10 @@ def testit(r_idx_type, c_idx_type, index_name):
820
852
821
853
# dt with dt
822
854
args = product (['dt' ], ['dt' ], ('index' , 'columns' ))
823
- for r_idx_type , c_idx_type , index_name in args :
824
- testit (r_idx_type , c_idx_type , index_name )
855
+ with warnings .catch_warnings (record = True ):
856
+ warnings .simplefilter ('always' , RuntimeWarning )
857
+ for r_idx_type , c_idx_type , index_name in args :
858
+ testit (r_idx_type , c_idx_type , index_name )
825
859
826
860
def test_basic_series_frame_alignment (self ):
827
861
for engine , parser in ENGINES_PARSERS :
@@ -831,20 +865,29 @@ def check_series_frame_commutativity(self, engine, parser):
831
865
tm .skip_if_no_ne (engine )
832
866
args = product (self .lhs_index_types , self .index_types , ('+' , '*' ),
833
867
('index' , 'columns' ))
834
- for r_idx_type , c_idx_type , op , index_name in args :
835
- df = mkdf (10 , 10 , data_gen_f = f , r_idx_type = r_idx_type ,
836
- c_idx_type = c_idx_type )
837
- index = getattr (df , index_name )
838
- s = Series (np .random .randn (5 ), index [:5 ])
839
868
840
- lhs = 's {0} df' .format (op )
841
- rhs = 'df {0} s' .format (op )
842
- a = pd .eval (lhs , engine = engine , parser = parser )
843
- b = pd .eval (rhs , engine = engine , parser = parser )
869
+ with warnings .catch_warnings (record = True ):
870
+ warnings .simplefilter ('always' , RuntimeWarning )
871
+ for r_idx_type , c_idx_type , op , index_name in args :
872
+ df = mkdf (10 , 10 , data_gen_f = f , r_idx_type = r_idx_type ,
873
+ c_idx_type = c_idx_type )
874
+ index = getattr (df , index_name )
875
+ s = Series (np .random .randn (5 ), index [:5 ])
876
+
877
+ lhs = 's {0} df' .format (op )
878
+ rhs = 'df {0} s' .format (op )
879
+ if should_warn (df .index , s .index ):
880
+ with tm .assert_produces_warning (RuntimeWarning ):
881
+ a = pd .eval (lhs , engine = engine , parser = parser )
882
+ with tm .assert_produces_warning (RuntimeWarning ):
883
+ b = pd .eval (rhs , engine = engine , parser = parser )
884
+ else :
885
+ a = pd .eval (lhs , engine = engine , parser = parser )
886
+ b = pd .eval (rhs , engine = engine , parser = parser )
844
887
845
- if r_idx_type != 'dt' and c_idx_type != 'dt' :
846
- if engine == 'numexpr' :
847
- assert_frame_equal (a , b )
888
+ if r_idx_type != 'dt' and c_idx_type != 'dt' :
889
+ if engine == 'numexpr' :
890
+ assert_frame_equal (a , b )
848
891
849
892
def test_series_frame_commutativity (self ):
850
893
for engine , parser in ENGINES_PARSERS :
@@ -860,34 +903,41 @@ def check_complex_series_frame_alignment(self, engine, parser):
860
903
m1 = 5
861
904
m2 = 2 * m1
862
905
863
- for r1 , r2 , c1 , c2 in args :
864
- index_name = random .choice (['index' , 'columns' ])
865
- obj_name = random .choice (['df' , 'df2' ])
866
-
867
- df = mkdf (m1 , n , data_gen_f = f , r_idx_type = r1 , c_idx_type = c1 )
868
- df2 = mkdf (m2 , n , data_gen_f = f , r_idx_type = r2 , c_idx_type = c2 )
869
- index = getattr (locals ().get (obj_name ), index_name )
870
- s = Series (np .random .randn (n ), index [:n ])
871
-
872
- if r2 == 'dt' or c2 == 'dt' :
873
- if engine == 'numexpr' :
874
- expected2 = df2 .add (s )
906
+ with warnings .catch_warnings (record = True ):
907
+ warnings .simplefilter ('always' , RuntimeWarning )
908
+ for r1 , r2 , c1 , c2 in args :
909
+ index_name = random .choice (['index' , 'columns' ])
910
+ obj_name = random .choice (['df' , 'df2' ])
911
+
912
+ df = mkdf (m1 , n , data_gen_f = f , r_idx_type = r1 , c_idx_type = c1 )
913
+ df2 = mkdf (m2 , n , data_gen_f = f , r_idx_type = r2 , c_idx_type = c2 )
914
+ index = getattr (locals ().get (obj_name ), index_name )
915
+ s = Series (np .random .randn (n ), index [:n ])
916
+
917
+ if r2 == 'dt' or c2 == 'dt' :
918
+ if engine == 'numexpr' :
919
+ expected2 = df2 .add (s )
920
+ else :
921
+ expected2 = df2 + s
875
922
else :
876
923
expected2 = df2 + s
877
- else :
878
- expected2 = df2 + s
879
924
880
- if r1 == 'dt' or c1 == 'dt' :
881
- if engine == 'numexpr' :
882
- expected = expected2 .add (df )
925
+ if r1 == 'dt' or c1 == 'dt' :
926
+ if engine == 'numexpr' :
927
+ expected = expected2 .add (df )
928
+ else :
929
+ expected = expected2 + df
883
930
else :
884
931
expected = expected2 + df
885
- else :
886
- expected = expected2 + df
887
932
888
- res = pd .eval ('df2 + s + df' , engine = engine , parser = parser )
889
- tm .assert_equal (res .shape , expected .shape )
890
- assert_frame_equal (res , expected )
933
+ if should_warn (df2 .index , s .index , df .index ):
934
+ with tm .assert_produces_warning (RuntimeWarning ):
935
+ res = pd .eval ('df2 + s + df' , engine = engine ,
936
+ parser = parser )
937
+ else :
938
+ res = pd .eval ('df2 + s + df' , engine = engine , parser = parser )
939
+ tm .assert_equal (res .shape , expected .shape )
940
+ assert_frame_equal (res , expected )
891
941
892
942
@slow
893
943
def test_complex_series_frame_alignment (self ):
0 commit comments