24
24
from pandas .core .config import get_option
25
25
from pandas .core import format as fmt
26
26
27
+ class OrderingWarning (Warning ): pass
28
+
27
29
def _cat_compare_op (op ):
28
30
def f (self , other ):
29
31
# On python2, you can usually compare any type to any type, and Categoricals can be
@@ -828,6 +830,18 @@ def T(self):
828
830
def nbytes (self ):
829
831
return self ._codes .nbytes + self ._categories .values .nbytes
830
832
833
+ def maybe_coerce_as_ordered (self ):
834
+ """
835
+ if we are not ordered, but try an ordering operation, let it succeed with a warning
836
+ This may return a new copy of the object
837
+ """
838
+ if not self .ordered :
839
+ warn ("Categorical is not ordered\n "
840
+ "sort will be in the order of the categories\n "
841
+ "you can use .as_ordered() to change the Categorical to an ordered one\n " ,
842
+ OrderingWarning )
843
+ return self
844
+
831
845
def searchsorted (self , v , side = 'left' , sorter = None ):
832
846
"""Find indices where elements should be inserted to maintain order.
833
847
@@ -847,6 +861,11 @@ def searchsorted(self, v, side='left', sorter=None):
847
861
Optional array of integer indices that sort `self` into ascending
848
862
order. They are typically the result of ``np.argsort``.
849
863
864
+ Warns
865
+ -----
866
+ OrderingWarning
867
+ If the `Categorical` is not `ordered`.
868
+
850
869
Returns
851
870
-------
852
871
indices : array of ints
@@ -878,9 +897,7 @@ def searchsorted(self, v, side='left', sorter=None):
878
897
>>> x.searchsorted(['bread', 'eggs'], side='right', sorter=[0, 1, 2, 3, 5, 4])
879
898
array([3, 5]) # eggs after donuts, after switching milk and donuts
880
899
"""
881
- if not self .ordered :
882
- raise ValueError ("Categorical not ordered\n "
883
- "you can use .as_ordered() to change the Categorical to an ordered one\n " )
900
+ self = self .maybe_coerce_as_ordered ()
884
901
885
902
from pandas .core .series import Series
886
903
values_as_codes = self .categories .values .searchsorted (Series (v ).values , side )
@@ -1003,13 +1020,17 @@ def argsort(self, ascending=True, **kwargs):
1003
1020
1004
1021
Only ordered Categoricals can be argsorted!
1005
1022
1023
+ Warns
1024
+ -----
1025
+ OrderingWarning
1026
+ If the `Categorical` is not `ordered`.
1027
+
1006
1028
Returns
1007
1029
-------
1008
1030
argsorted : numpy array
1009
1031
"""
1010
- if not self .ordered :
1011
- raise TypeError ("Categorical not ordered\n "
1012
- "you can use .as_ordered() to change the Categorical to an ordered one\n " )
1032
+
1033
+ self = self .maybe_coerce_as_ordered ()
1013
1034
result = np .argsort (self ._codes .copy (), ** kwargs )
1014
1035
if not ascending :
1015
1036
result = result [::- 1 ]
@@ -1032,6 +1053,11 @@ def order(self, inplace=False, ascending=True, na_position='last'):
1032
1053
'first' puts NaNs at the beginning
1033
1054
'last' puts NaNs at the end
1034
1055
1056
+ Warns
1057
+ -----
1058
+ OrderingWarning
1059
+ If the `Categorical` is not `ordered`.
1060
+
1035
1061
Returns
1036
1062
-------
1037
1063
y : Category or None
@@ -1040,9 +1066,8 @@ def order(self, inplace=False, ascending=True, na_position='last'):
1040
1066
--------
1041
1067
Category.sort
1042
1068
"""
1043
- if not self .ordered :
1044
- raise TypeError ("Categorical not ordered\n "
1045
- "you can use .as_ordered() to change the Categorical to an ordered one\n " )
1069
+
1070
+ self = self .maybe_coerce_as_ordered ()
1046
1071
if na_position not in ['last' ,'first' ]:
1047
1072
raise ValueError ('invalid na_position: {!r}' .format (na_position ))
1048
1073
@@ -1092,6 +1117,11 @@ def sort(self, inplace=True, ascending=True, na_position='last'):
1092
1117
'first' puts NaNs at the beginning
1093
1118
'last' puts NaNs at the end
1094
1119
1120
+ Warns
1121
+ -----
1122
+ OrderingWarning
1123
+ If the `Categorical` is not `ordered`.
1124
+
1095
1125
Returns
1096
1126
-------
1097
1127
y : Category or None
@@ -1413,18 +1443,16 @@ def min(self, numeric_only=None, **kwargs):
1413
1443
1414
1444
Only ordered `Categoricals` have a minimum!
1415
1445
1416
- Raises
1417
- ------
1418
- TypeError
1446
+ Warns
1447
+ -----
1448
+ OrderingWarning
1419
1449
If the `Categorical` is not `ordered`.
1420
1450
1421
1451
Returns
1422
1452
-------
1423
1453
min : the minimum of this `Categorical`
1424
1454
"""
1425
- if not self .ordered :
1426
- raise TypeError ("Categorical not ordered\n "
1427
- "you can use .as_ordered() to change the Categorical to an ordered one\n " )
1455
+ self = self .maybe_coerce_as_ordered ()
1428
1456
if numeric_only :
1429
1457
good = self ._codes != - 1
1430
1458
pointer = self ._codes [good ].min (** kwargs )
@@ -1441,18 +1469,16 @@ def max(self, numeric_only=None, **kwargs):
1441
1469
1442
1470
Only ordered `Categoricals` have a maximum!
1443
1471
1444
- Raises
1445
- ------
1446
- TypeError
1472
+ Warns
1473
+ -----
1474
+ OrderingWarning
1447
1475
If the `Categorical` is not `ordered`.
1448
1476
1449
1477
Returns
1450
1478
-------
1451
1479
max : the maximum of this `Categorical`
1452
1480
"""
1453
- if not self .ordered :
1454
- raise TypeError ("Categorical not ordered\n "
1455
- "you can use .as_ordered() to change the Categorical to an ordered one\n " )
1481
+ self = self .maybe_coerce_as_ordered ()
1456
1482
if numeric_only :
1457
1483
good = self ._codes != - 1
1458
1484
pointer = self ._codes [good ].max (** kwargs )
0 commit comments