9
9
from pandas import (
10
10
Series , Categorical , CategoricalIndex , IntervalIndex , date_range )
11
11
12
- from pandas .compat import string_types
13
12
from pandas .core .dtypes .dtypes import (
14
13
DatetimeTZDtype , PeriodDtype ,
15
14
IntervalDtype , CategoricalDtype )
24
23
import pandas .util .testing as tm
25
24
26
25
26
+ @pytest .fixture (scope = 'class' , params = [True , False , None ])
27
+ def ordered (request ):
28
+ return request .param
29
+
30
+
27
31
class Base (object ):
28
32
29
33
def setup_method (self , method ):
@@ -124,41 +128,6 @@ def test_tuple_categories(self):
124
128
result = CategoricalDtype (categories )
125
129
assert all (result .categories == categories )
126
130
127
- @pytest .mark .parametrize ('dtype' , [
128
- CategoricalDtype (list ('abc' ), False ),
129
- CategoricalDtype (list ('abc' ), True )])
130
- @pytest .mark .parametrize ('new_dtype' , [
131
- 'category' ,
132
- CategoricalDtype (None , False ),
133
- CategoricalDtype (None , True ),
134
- CategoricalDtype (list ('abc' ), False ),
135
- CategoricalDtype (list ('abc' ), True ),
136
- CategoricalDtype (list ('cba' ), False ),
137
- CategoricalDtype (list ('cba' ), True ),
138
- CategoricalDtype (list ('wxyz' ), False ),
139
- CategoricalDtype (list ('wxyz' ), True )])
140
- def test_update_dtype (self , dtype , new_dtype ):
141
- if isinstance (new_dtype , string_types ) and new_dtype == 'category' :
142
- expected_categories = dtype .categories
143
- expected_ordered = dtype .ordered
144
- else :
145
- expected_categories = new_dtype .categories
146
- if expected_categories is None :
147
- expected_categories = dtype .categories
148
- expected_ordered = new_dtype .ordered
149
-
150
- result = dtype ._update_dtype (new_dtype )
151
- tm .assert_index_equal (result .categories , expected_categories )
152
- assert result .ordered is expected_ordered
153
-
154
- @pytest .mark .parametrize ('bad_dtype' , [
155
- 'foo' , object , np .int64 , PeriodDtype ('Q' ), IntervalDtype (object )])
156
- def test_update_dtype_errors (self , bad_dtype ):
157
- dtype = CategoricalDtype (list ('abc' ), False )
158
- msg = 'a CategoricalDtype must be passed to perform an update, '
159
- with tm .assert_raises_regex (ValueError , msg ):
160
- dtype ._update_dtype (bad_dtype )
161
-
162
131
163
132
class TestDatetimeTZDtype (Base ):
164
133
@@ -568,39 +537,37 @@ def test_caching(self):
568
537
569
538
class TestCategoricalDtypeParametrized (object ):
570
539
571
- @pytest .mark .parametrize ('categories, ordered' , [
572
- (['a' , 'b' , 'c' , 'd' ], False ),
573
- (['a' , 'b' , 'c' , 'd' ], True ),
574
- (np .arange (1000 ), False ),
575
- (np .arange (1000 ), True ),
576
- (['a' , 'b' , 10 , 2 , 1.3 , True ], False ),
577
- ([True , False ], True ),
578
- ([True , False ], False ),
579
- (pd .date_range ('2017' , periods = 4 ), True ),
580
- (pd .date_range ('2017' , periods = 4 ), False ),
581
- ])
540
+ @pytest .mark .parametrize ('categories' , [
541
+ list ('abcd' ),
542
+ np .arange (1000 ),
543
+ ['a' , 'b' , 10 , 2 , 1.3 , True ],
544
+ [True , False ],
545
+ pd .date_range ('2017' , periods = 4 )])
582
546
def test_basic (self , categories , ordered ):
583
547
c1 = CategoricalDtype (categories , ordered = ordered )
584
548
tm .assert_index_equal (c1 .categories , pd .Index (categories ))
585
549
assert c1 .ordered is ordered
586
550
587
551
def test_order_matters (self ):
588
552
categories = ['a' , 'b' ]
589
- c1 = CategoricalDtype (categories , ordered = False )
590
- c2 = CategoricalDtype (categories , ordered = True )
553
+ c1 = CategoricalDtype (categories , ordered = True )
554
+ c2 = CategoricalDtype (categories , ordered = False )
555
+ c3 = CategoricalDtype (categories , ordered = None )
591
556
assert c1 is not c2
557
+ assert c1 is not c3
592
558
593
- def test_unordered_same (self ):
594
- c1 = CategoricalDtype (['a' , 'b' ])
595
- c2 = CategoricalDtype (['b' , 'a' ])
559
+ @pytest .mark .parametrize ('ordered' , [False , None ])
560
+ def test_unordered_same (self , ordered ):
561
+ c1 = CategoricalDtype (['a' , 'b' ], ordered = ordered )
562
+ c2 = CategoricalDtype (['b' , 'a' ], ordered = ordered )
596
563
assert hash (c1 ) == hash (c2 )
597
564
598
565
def test_categories (self ):
599
566
result = CategoricalDtype (['a' , 'b' , 'c' ])
600
567
tm .assert_index_equal (result .categories , pd .Index (['a' , 'b' , 'c' ]))
601
- assert result .ordered is False
568
+ assert result .ordered is None
602
569
603
- def test_equal_but_different (self ):
570
+ def test_equal_but_different (self , ordered ):
604
571
c1 = CategoricalDtype ([1 , 2 , 3 ])
605
572
c2 = CategoricalDtype ([1. , 2. , 3. ])
606
573
assert c1 is not c2
@@ -611,9 +578,11 @@ def test_equal_but_different(self):
611
578
([1 , 2 , 3 ], [3 , 2 , 1 ]),
612
579
])
613
580
def test_order_hashes_different (self , v1 , v2 ):
614
- c1 = CategoricalDtype (v1 )
581
+ c1 = CategoricalDtype (v1 , ordered = False )
615
582
c2 = CategoricalDtype (v2 , ordered = True )
583
+ c3 = CategoricalDtype (v1 , ordered = None )
616
584
assert c1 is not c2
585
+ assert c1 is not c3
617
586
618
587
def test_nan_invalid (self ):
619
588
with pytest .raises (ValueError ):
@@ -628,26 +597,35 @@ def test_same_categories_different_order(self):
628
597
c2 = CategoricalDtype (['b' , 'a' ], ordered = True )
629
598
assert c1 is not c2
630
599
631
- @pytest .mark .parametrize ('ordered, other, expected' , [
632
- (True , CategoricalDtype (['a' , 'b' ], True ), True ),
633
- (False , CategoricalDtype (['a' , 'b' ], False ), True ),
634
- (True , CategoricalDtype (['a' , 'b' ], False ), False ),
635
- (False , CategoricalDtype (['a' , 'b' ], True ), False ),
636
- (True , CategoricalDtype ([1 , 2 ], False ), False ),
637
- (False , CategoricalDtype ([1 , 2 ], True ), False ),
638
- (False , CategoricalDtype (None , True ), True ),
639
- (True , CategoricalDtype (None , True ), True ),
640
- (False , CategoricalDtype (None , False ), True ),
641
- (True , CategoricalDtype (None , False ), True ),
642
- (True , 'category' , True ),
643
- (False , 'category' , True ),
644
- (True , 'not a category' , False ),
645
- (False , 'not a category' , False ),
646
- ])
647
- def test_categorical_equality (self , ordered , other , expected ):
648
- c1 = CategoricalDtype (['a' , 'b' ], ordered )
600
+ @pytest .mark .parametrize ('ordered1' , [True , False , None ])
601
+ @pytest .mark .parametrize ('ordered2' , [True , False , None ])
602
+ def test_categorical_equality (self , ordered1 , ordered2 ):
603
+ # same categories
604
+ c1 = CategoricalDtype (list ('abc' ), ordered1 )
605
+ c2 = CategoricalDtype (list ('abc' ), ordered2 )
606
+ result = c1 == c2
607
+ expected = (ordered1 is ordered2 ) or not any ([ordered1 , ordered2 ])
608
+ assert result is expected
609
+
610
+ # different categories
611
+ c2 = CategoricalDtype ([1 , 2 , 3 ], ordered2 )
612
+ assert c1 != c2
613
+
614
+ # none categories
615
+ c1 = CategoricalDtype (list ('abc' ), ordered1 )
616
+ c2 = CategoricalDtype (None , ordered2 )
617
+ c3 = CategoricalDtype (None , ordered1 )
618
+ assert c1 == c2
619
+ assert c2 == c1
620
+ assert c2 == c3
621
+
622
+ @pytest .mark .parametrize ('categories' , [list ('abc' ), None ])
623
+ @pytest .mark .parametrize ('other' , ['category' , 'not a category' ])
624
+ def test_categorical_equality_strings (self , categories , ordered , other ):
625
+ c1 = CategoricalDtype (categories , ordered )
649
626
result = c1 == other
650
- assert result == expected
627
+ expected = other == 'category'
628
+ assert result is expected
651
629
652
630
def test_invalid_raises (self ):
653
631
with tm .assert_raises_regex (TypeError , 'ordered' ):
@@ -688,16 +666,51 @@ def test_from_categorical_dtype_both(self):
688
666
c1 , categories = [1 , 2 ], ordered = False )
689
667
assert result == CategoricalDtype ([1 , 2 ], ordered = False )
690
668
691
- def test_str_vs_repr (self ):
692
- c1 = CategoricalDtype (['a' , 'b' ])
669
+ def test_str_vs_repr (self , ordered ):
670
+ c1 = CategoricalDtype (['a' , 'b' ], ordered = ordered )
693
671
assert str (c1 ) == 'category'
694
672
# Py2 will have unicode prefixes
695
- pat = r"CategoricalDtype\(categories=\[.*\], ordered=False \)"
696
- assert re .match (pat , repr (c1 ))
673
+ pat = r"CategoricalDtype\(categories=\[.*\], ordered={ordered} \)"
674
+ assert re .match (pat . format ( ordered = ordered ) , repr (c1 ))
697
675
698
676
def test_categorical_categories (self ):
699
677
# GH17884
700
678
c1 = CategoricalDtype (Categorical (['a' , 'b' ]))
701
679
tm .assert_index_equal (c1 .categories , pd .Index (['a' , 'b' ]))
702
680
c1 = CategoricalDtype (CategoricalIndex (['a' , 'b' ]))
703
681
tm .assert_index_equal (c1 .categories , pd .Index (['a' , 'b' ]))
682
+
683
+ @pytest .mark .parametrize ('new_categories' , [
684
+ list ('abc' ), list ('cba' ), list ('wxyz' ), None ])
685
+ @pytest .mark .parametrize ('new_ordered' , [True , False , None ])
686
+ def test_update_dtype (self , ordered , new_categories , new_ordered ):
687
+ dtype = CategoricalDtype (list ('abc' ), ordered )
688
+ new_dtype = CategoricalDtype (new_categories , new_ordered )
689
+
690
+ expected_categories = new_dtype .categories
691
+ if expected_categories is None :
692
+ expected_categories = dtype .categories
693
+
694
+ expected_ordered = new_dtype .ordered
695
+ if expected_ordered is None :
696
+ expected_ordered = dtype .ordered
697
+
698
+ result = dtype ._update_dtype (new_dtype )
699
+ tm .assert_index_equal (result .categories , expected_categories )
700
+ assert result .ordered is expected_ordered
701
+
702
+ def test_update_dtype_string (self , ordered ):
703
+ dtype = CategoricalDtype (list ('abc' ), ordered )
704
+ expected_categories = dtype .categories
705
+ expected_ordered = dtype .ordered
706
+ result = dtype ._update_dtype ('category' )
707
+ tm .assert_index_equal (result .categories , expected_categories )
708
+ assert result .ordered is expected_ordered
709
+
710
+ @pytest .mark .parametrize ('bad_dtype' , [
711
+ 'foo' , object , np .int64 , PeriodDtype ('Q' ), IntervalDtype (object )])
712
+ def test_update_dtype_errors (self , bad_dtype ):
713
+ dtype = CategoricalDtype (list ('abc' ), False )
714
+ msg = 'a CategoricalDtype must be passed to perform an update, '
715
+ with tm .assert_raises_regex (ValueError , msg ):
716
+ dtype ._update_dtype (bad_dtype )
0 commit comments