Categorical#

class Categorical#

Represent a categorical variable in pandas.

Example#

import pandasCore as pd

# Create Categorical
obj = pd.Categorical(...)

Attributes#

Attribute

Description

Example

T

Return transposed Categorical (alias for transpose()).

View

categories

The categories of this categorical

View

codes

The category codes of this categorical

View

empty

Whether the array is empty

View

nbytes

Memory usage in bytes

View

ndim

Number of dimensions (always 1)

View

ordered

Whether the categorical is ordered

View

shape

Shape of the array

View

size

Number of elements

View

Construction#

Method

Description

Example

__init__() (*args, **kwargs) | () | (values: list, categories: object = None, ordered: object = None, dtype: object = None, fastpath: object = None, copy: bool = True)

Create an empty Categorical

View

Indexing / Selection#

Method

Description

Example

__getitem__() (idx: typing.SupportsInt)

Get element by position

take() (indices: collections.abc.Sequence[typing.SupportsInt], *, allow_fill: bool = False, fill_value: object = None, axis: typing.SupportsInt = 0)

Take elements from the Categorical.

View

Data Manipulation#

Method

Description

Example

insert() (loc: typing.SupportsInt, item: object)

Insert element at position.

View

Missing Data#

Method

Description

Example

dropna() ()

Return Categorical without NA values.

View

fillna() (value: object = None, method: object = None, limit: object = None, copy: bool = True)

Fill NA/NaN values using the specified value.

View

interpolate() (method: str = 'pad', *, axis: typing.SupportsInt = 0, index: object = None, limit: object = None, limit_direction: str = 'forward', limit_area: object = None, copy: bool = True, **kwargs)

Fill NA/NaN values using the specified method.

View

isna() ()

Detect missing values.

View

isnull() ()

Detect missing values (alias for isna).

View

notna() ()

Detect existing (non-missing) values.

View

notnull() ()

Detect existing (non-missing) values (alias for notna).

View

Statistics#

Method

Description

Example

describe() ()

Generate descriptive statistics.

View

max() (*, skipna: bool = True, **kwargs)

Return the maximum value.

View

min() (*, skipna: bool = True, **kwargs)

Return the minimum value.

View

value_counts() (dropna: bool = True)

Return a dict containing counts of unique values.

View

Aggregation#

Method

Description

Example

map() (mapper: object, na_action: object = None)

Map values using input dict.

View

Comparison#

Method

Description

Example

__eq__() (self, value, /)

Return self==value.

__ge__() (self, value, /)

Return self>=value.

__gt__() (self, value, /)

Return self>value.

__le__() (self, value, /)

Return self<=value.

__lt__() (self, value, /)

Return self<value.

__ne__() (self, value, /)

Return self!=value.

equals() (other: pandasCore.Categorical)

Test whether two Categoricals are equivalent.

Sorting#

Method

Description

Example

argsort() (*, ascending: bool = True, kind: str = 'quicksort', **kwargs)

Return the integer indices that would sort the values.

View

searchsorted() (value: object, side: str = 'left', sorter: object = None)

Find indices where elements should be inserted to maintain order.

View

sort_values() (*, inplace: bool = False, ascending: bool = True, na_position: str = 'last')

Sort by the values.

View

Reshaping#

Method

Description

Example

swapaxes() (axis1: typing.SupportsInt, axis2: typing.SupportsInt)

Interchange axes of the Categorical.

View

transpose() (*args)

Return transposed Categorical.

View

Time Series#

Method

Description

Example

shift() (periods: typing.SupportsInt = 1, fill_value: object = None)

Shift values by desired number of periods.

View

I/O#

Method

Description

Example

to_list() ()

Return a list of the values.

View

to_numpy() (dtype: object = None, copy: bool = False, na_value: object = None)

Return a NumPy array of the values (codes).

View

tolist() ()

Return a list of the values.

View

Conversion#

Method

Description

Example

astype() (dtype: object, copy: bool = True)

Cast to a specified dtype.

View

copy() (order: str = 'C')

Return a copy of the Categorical.

View

view() (dtype: object = None)

Return a view on the array.

View

Iteration#

Method

Description

Example

__len__() ()

Return the number of elements

Set Operations#

Method

Description

Example

duplicated() (keep: str = 'first')

Indicate duplicate values.

View

isin() (values: collections.abc.Sequence[str])

Check whether values are contained in Categorical.

View

unique() ()

Return unique values.

View

Categorical Methods#

Method

Description

Example

add_categories() (new_categories: collections.abc.Sequence[str])

Add new categories.

View

as_ordered() ()

Set the Categorical to be ordered.

View

as_unordered() ()

Set the Categorical to be unordered.

View

remove_categories() (removals: collections.abc.Sequence[str])

Remove the specified categories.

View

remove_unused_categories() ()

Remove categories which are not used.

View

rename_categories() (new_categories: collections.abc.Sequence[str])

Rename categories.

View

reorder_categories() (new_categories: collections.abc.Sequence[str], ordered: bool | None = None)

Reorder categories as specified in new_categories.

View

set_categories() (new_categories: collections.abc.Sequence[str], ordered: bool | None = None, rename: bool = False)

Set the categories to the specified new_categories.

View

Other Methods#

Method

Description

Example

__hash__() (self, /)

Return hash(self).

__repr__() ()

__str__() ()

argmax() (axis: typing.SupportsInt = 0, skipna: bool = True)

Return the index of the maximum value.

View

argmin() (axis: typing.SupportsInt = 0, skipna: bool = True)

Return the index of the minimum value.

View

check_for_ordered() (op: str)

Assert that the Categorical is ordered.

delete() (loc: object, axis: typing.SupportsInt = 0)

Delete element at position.

View

factorize() (use_na_sentinel: bool = True)

Encode the object as an enumerated type.

View

memory_usage() (deep: bool = False)

Return the memory usage of the Categorical.

View

ravel() (order: str = 'C')

Return a flattened (1-dimensional) Categorical.

View

repeat() (repeats: object, axis: typing.SupportsInt = 0)

Repeat elements of a Categorical.

View

reshape() (shape: object)

Return a Categorical with the same data but a different shape.

View

set_ordered() (value: bool)

Set the ordered attribute to the boolean value.

View

Code Examples#

The following examples are extracted from the test suite.

T (test_categorical.py:2112)
2102            return False
2103
2104        # Test values match pandas
2105        if transposed.to_list() == list(transposed_pd):
2106            f_print_success("transpose() values match pandas")
2107        else:
2108            f_print_error(f"transpose() values mismatch")
2109            return False
2110
2111        # Test T property (alias for transpose)
2112        t_prop = cat.T
2113        if t_prop.to_list() == list(cat_pd.T):
2114            f_print_success("T property matches pandas")
2115        else:
2116            f_print_error(f"T property mismatch")
2117            return False
2118
2119        return True
2120
2121    except Exception as e:
2122        f_print_error(f"Exception: {e}")
categories (test_accessor_descriptor.py:220)
210        f_print_info(f"type(s.cat).__name__ = {type_name}")
211
212        if type_name == "CategoricalAccessor":
213            f_print_success("s.cat returns CategoricalAccessor")
214        else:
215            f_print_error(f"Expected CategoricalAccessor, got {type_name}")
216            return False
217
218        # Test categories property
219        categories = cat_accessor.categories
220        f_print_success(f"cat.categories: {categories}")
221
222        return True
223
224    except Exception as e:
225        f_print_error(f"Exception: {e}")
226        return False
227
228
229def test_datetime_series_dt_accessor():
230    """Test that DatetimeSeries.dt accessor works on instance"""
codes (test_categorical.py:104)
 94            return False
 95
 96        # Compare ordered with pandas
 97        if cat.ordered == cat_pd.ordered:
 98            f_print_success(f"ordered matches pandas: {cat.ordered}")
 99        else:
100            f_print_error(f"ordered mismatch: pandasCore={cat.ordered}, pandas={cat_pd.ordered}")
101            return False
102
103        # Compare codes length with pandas
104        if len(cat.codes) == len(cat_pd.codes):
105            f_print_success(f"codes length matches pandas: {len(cat.codes)}")
106        else:
107            f_print_error(f"codes length mismatch: pandasCore={len(cat.codes)}, pandas={len(cat_pd.codes)}")
108            return False
109
110        return True
111
112    except Exception as e:
113        f_print_error(f"Exception: {e}")
114        return False
empty (test_categorical.py:46)
36        # Compare size with pandas
37        if cat.size == cat_pd.size:
38            f_print_success(f"size matches pandas: {cat.size}")
39        else:
40            f_print_error(f"size mismatch: pandasCore={cat.size}, pandas={cat_pd.size}")
41            return False
42
43        # Check empty property (note: pandas Categorical doesn't have .empty, but pandasCore does)
44        # We verify empty is True when size is 0
45        expected_empty = (cat_pd.size == 0)
46        if cat.empty == expected_empty:
47            f_print_success(f"empty property matches expected: {cat.empty}")
48        else:
49            f_print_error(f"empty mismatch: pandasCore={cat.empty}, expected={expected_empty}")
50            return False
51
52        # Compare ordered with pandas
53        if cat.ordered == cat_pd.ordered:
54            f_print_success(f"ordered matches pandas: {cat.ordered}")
55        else:
56            f_print_error(f"ordered mismatch: pandasCore={cat.ordered}, pandas={cat_pd.ordered}")
nbytes (test_categorical.py:229)
219            return False
220
221        # Compare shape with pandas
222        if cat.shape == cat_pd.shape:
223            f_print_success(f"shape matches pandas: {cat.shape}")
224        else:
225            f_print_error(f"shape mismatch: pandasCore={cat.shape}, pandas={cat_pd.shape}")
226            return False
227
228        # Compare nbytes with pandas
229        if cat.nbytes > 0 and cat_pd.nbytes > 0:
230            f_print_success(f"nbytes both positive: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}")
231        else:
232            f_print_error(f"nbytes should be > 0: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}")
233            return False
234
235        return True
236
237    except Exception as e:
238        f_print_error(f"Exception: {e}")
239        return False
ndim (test_categorical.py:215)
205        # Check empty (pandas Categorical doesn't have .empty, compare with size==0)
206        expected_empty = (cat_pd.size == 0)
207        if cat.empty == expected_empty:
208            f_print_success(f"empty matches expected: {cat.empty}")
209        else:
210            f_print_error(f"empty mismatch: pandasCore={cat.empty}, expected={expected_empty}")
211            return False
212
213        # Compare ndim with pandas
214        if cat.ndim == cat_pd.ndim:
215            f_print_success(f"ndim matches pandas: {cat.ndim}")
216        else:
217            f_print_error(f"ndim mismatch: pandasCore={cat.ndim}, pandas={cat_pd.ndim}")
218            return False
219
220        # Compare shape with pandas
221        if cat.shape == cat_pd.shape:
222            f_print_success(f"shape matches pandas: {cat.shape}")
223        else:
224            f_print_error(f"shape mismatch: pandasCore={cat.shape}, pandas={cat_pd.shape}")
ordered (test_categorical.py:53)
43        # Check empty property (note: pandas Categorical doesn't have .empty, but pandasCore does)
44        # We verify empty is True when size is 0
45        expected_empty = (cat_pd.size == 0)
46        if cat.empty == expected_empty:
47            f_print_success(f"empty property matches expected: {cat.empty}")
48        else:
49            f_print_error(f"empty mismatch: pandasCore={cat.empty}, expected={expected_empty}")
50            return False
51
52        # Compare ordered with pandas
53        if cat.ordered == cat_pd.ordered:
54            f_print_success(f"ordered matches pandas: {cat.ordered}")
55        else:
56            f_print_error(f"ordered mismatch: pandasCore={cat.ordered}, pandas={cat_pd.ordered}")
57            return False
58
59        # Compare categories with pandas
60        if len(cat.categories) == len(cat_pd.categories):
61            f_print_success(f"categories length matches pandas: {len(cat.categories)}")
62        else:
63            f_print_error(f"categories mismatch: pandasCore={cat.categories}, pandas={list(cat_pd.categories)}")
shape (test_categorical.py:222)
212            return False
213
214        # Compare ndim with pandas
215        if cat.ndim == cat_pd.ndim:
216            f_print_success(f"ndim matches pandas: {cat.ndim}")
217        else:
218            f_print_error(f"ndim mismatch: pandasCore={cat.ndim}, pandas={cat_pd.ndim}")
219            return False
220
221        # Compare shape with pandas
222        if cat.shape == cat_pd.shape:
223            f_print_success(f"shape matches pandas: {cat.shape}")
224        else:
225            f_print_error(f"shape mismatch: pandasCore={cat.shape}, pandas={cat_pd.shape}")
226            return False
227
228        # Compare nbytes with pandas
229        if cat.nbytes > 0 and cat_pd.nbytes > 0:
230            f_print_success(f"nbytes both positive: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}")
231        else:
232            f_print_error(f"nbytes should be > 0: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}")
size (test_categorical.py:37)
27def test_empty_categorical():
28    """Test empty Categorical constructor"""
29    f_print_header("Test: Empty Categorical")
30
31    try:
32        cat = pandasCore.Categorical()
33        cat_pd = pd.Categorical([])
34        f_print_success("Created empty Categorical")
35
36        # Compare size with pandas
37        if cat.size == cat_pd.size:
38            f_print_success(f"size matches pandas: {cat.size}")
39        else:
40            f_print_error(f"size mismatch: pandasCore={cat.size}, pandas={cat_pd.size}")
41            return False
42
43        # Check empty property (note: pandas Categorical doesn't have .empty, but pandasCore does)
44        # We verify empty is True when size is 0
45        expected_empty = (cat_pd.size == 0)
46        if cat.empty == expected_empty:
47            f_print_success(f"empty property matches expected: {cat.empty}")
__init__ (test_categorical.py:32)
22# Direct imports
23import pandasCore
24import pandas as pd
25
26
27def test_empty_categorical():
28    """Test empty Categorical constructor"""
29    f_print_header("Test: Empty Categorical")
30
31    try:
32        cat = pandasCore.Categorical()
33        cat_pd = pd.Categorical([])
34        f_print_success("Created empty Categorical")
35
36        # Compare size with pandas
37        if cat.size == cat_pd.size:
38            f_print_success(f"size matches pandas: {cat.size}")
39        else:
40            f_print_error(f"size mismatch: pandasCore={cat.size}, pandas={cat_pd.size}")
41            return False
take (test_categorical.py:802)
792        return False
793
794
795def test_take():
796    """Test take method"""
797    f_print_header("Test: take")
798
799    try:
800        cat = pandasCore.Categorical(['a', 'b', 'c', 'd', 'e'])
801        cat_pd = pd.Categorical(['a', 'b', 'c', 'd', 'e'])
802        cat2 = cat.take([0, 2, 4])
803        cat2_pd = cat_pd.take([0, 2, 4])
804
805        # Compare take size with pandas
806        if cat2.size == cat2_pd.size:
807            f_print_success(f"take size matches pandas: {cat2.size}")
808        else:
809            f_print_error(f"take size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}")
810            return False
811
812        # Compare take values with pandas
insert (test_categorical.py:1077)
1067def test_insert():
1068    """Test insert method"""
1069    f_print_header("Test: insert")
1070
1071    try:
1072        import numpy as np
1073        cat = pandasCore.Categorical(['a', 'b', 'c'])
1074        cat_pd = pd.Categorical(['a', 'b', 'c'])
1075        cat2 = cat.insert(1, 'b')  # Insert 'b' at index 1 (must be existing category)
1076        cat2_pd = cat_pd.insert(1, 'b')
1077
1078        # Compare insert size with pandas
1079        if cat2.size == cat2_pd.size:
1080            f_print_success(f"insert size matches pandas: {cat2.size}")
1081        else:
1082            f_print_error(f"insert size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}")
1083            return False
1084
1085        # Compare insert values with pandas
dropna (test_categorical.py:1012)
1002def test_dropna():
1003    """Test dropna method"""
1004    f_print_header("Test: dropna")
1005
1006    try:
1007        import numpy as np
1008        cat = pandasCore.Categorical(['a', None, 'b', None, 'c'])
1009        cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan, 'c'])
1010        cat2 = cat.dropna()
1011        cat2_pd = cat_pd.dropna()
1012
1013        # Compare dropna size with pandas
1014        if cat2.size == cat2_pd.size:
1015            f_print_success(f"dropna size matches pandas: {cat2.size}")
1016        else:
1017            f_print_error(f"dropna size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}")
1018            return False
1019
1020        # Compare values with pandas
fillna (test_categorical.py:974)
964def test_fillna():
965    """Test fillna method"""
966    f_print_header("Test: fillna")
967
968    try:
969        import numpy as np
970        # fillna requires value to be in categories - use an existing category
971        cat = pandasCore.Categorical(['a', None, 'b', None])
972        cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan])
973        cat2 = cat.fillna('a')  # Use 'a' which is in categories
974        cat2_pd = cat_pd.fillna('a')
975
976        # Compare fillna result with pandas
977        for i in range(len(cat2)):
978            if cat2[i] == cat2_pd[i]:
979                f_print_success(f"fillna cat2[{i}] matches pandas: {cat2[i]}")
980            else:
981                f_print_error(f"fillna cat2[{i}] mismatch: pandasCore={cat2[i]}, pandas={cat2_pd[i]}")
982                return False
interpolate (test_categorical.py:1224)
1214    """Test interpolate method with full pandas 2.x compatible parameters"""
1215    f_print_header("Test: interpolate")
1216
1217    try:
1218        import numpy as np
1219
1220        # Test data: NA, a, NA, NA, b, NA
1221        cat = pandasCore.Categorical([None, 'a', None, None, 'b', None])
1222
1223        # Test 1: Basic forward fill (default)
1224        cat_ffill = cat.interpolate(method='ffill')
1225        expected_ffill = [None, 'a', 'a', 'a', 'b', 'b']
1226        result_ffill = cat_ffill.tolist()
1227        if result_ffill == expected_ffill:
1228            f_print_success(f"interpolate ffill: {result_ffill}")
1229        else:
1230            f_print_error(f"interpolate ffill mismatch: got {result_ffill}, expected {expected_ffill}")
1231            return False
1232
1233        # Test 2: Backward fill
1234        cat_bfill = cat.interpolate(method='bfill')
isna (test_categorical.py:1333)
1323def test_isna_notna():
1324    """Test isna and notna methods"""
1325    f_print_header("Test: isna / notna")
1326
1327    try:
1328        import numpy as np
1329        cat = pandasCore.Categorical(['a', None, 'b', None])
1330        cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan])
1331
1332        isna_result = cat.isna()
1333        isna_result_pd = list(cat_pd.isna())
1334        if isna_result == isna_result_pd:
1335            f_print_success(f"isna() matches pandas: {isna_result}")
1336        else:
1337            f_print_error(f"isna() mismatch: pandasCore={isna_result}, pandas={isna_result_pd}")
1338            return False
1339
1340        notna_result = cat.notna()
1341        notna_result_pd = list(cat_pd.notna())
1342        if notna_result == notna_result_pd:
isnull (test_categorical.py:1366)
1356def test_isnull_notnull():
1357    """Test isnull and notnull methods (aliases for isna/notna)"""
1358    f_print_header("Test: isnull / notnull (Phase 4)")
1359
1360    try:
1361        import numpy as np
1362        cat = pandasCore.Categorical(['a', None, 'b', None, 'c'])
1363        cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan, 'c'])
1364
1365        # Compare isnull with pandas
1366        isnull_result = cat.isnull()
1367        isnull_result_pd = list(cat_pd.isnull())
1368        if isnull_result == isnull_result_pd:
1369            f_print_success(f"isnull() matches pandas: {isnull_result}")
1370        else:
1371            f_print_error(f"isnull() mismatch: pandasCore={isnull_result}, pandas={isnull_result_pd}")
1372            return False
1373
1374        # Compare notnull with pandas
1375        notnull_result = cat.notnull()
1376        notnull_result_pd = list(cat_pd.notnull())
notna (test_categorical.py:1341)
1331        cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan])
1332
1333        isna_result = cat.isna()
1334        isna_result_pd = list(cat_pd.isna())
1335        if isna_result == isna_result_pd:
1336            f_print_success(f"isna() matches pandas: {isna_result}")
1337        else:
1338            f_print_error(f"isna() mismatch: pandasCore={isna_result}, pandas={isna_result_pd}")
1339            return False
1340
1341        notna_result = cat.notna()
1342        notna_result_pd = list(cat_pd.notna())
1343        if notna_result == notna_result_pd:
1344            f_print_success(f"notna() matches pandas: {notna_result}")
1345        else:
1346            f_print_error(f"notna() mismatch: pandasCore={notna_result}, pandas={notna_result_pd}")
1347            return False
1348
1349        return True
1350
1351    except Exception as e:
notnull (test_categorical.py:1375)
1365        # Compare isnull with pandas
1366        isnull_result = cat.isnull()
1367        isnull_result_pd = list(cat_pd.isnull())
1368        if isnull_result == isnull_result_pd:
1369            f_print_success(f"isnull() matches pandas: {isnull_result}")
1370        else:
1371            f_print_error(f"isnull() mismatch: pandasCore={isnull_result}, pandas={isnull_result_pd}")
1372            return False
1373
1374        # Compare notnull with pandas
1375        notnull_result = cat.notnull()
1376        notnull_result_pd = list(cat_pd.notnull())
1377        if notnull_result == notnull_result_pd:
1378            f_print_success(f"notnull() matches pandas: {notnull_result}")
1379        else:
1380            f_print_error(f"notnull() mismatch: pandasCore={notnull_result}, pandas={notnull_result_pd}")
1381            return False
1382
1383        # Verify isna and notna are inverses
1384        isna_result = cat.isna()
1385        notna_result = cat.notna()
describe (test_categorical.py:1632)
1622        return False
1623
1624
1625def test_describe():
1626    """Test describe method"""
1627    f_print_header("Test: describe")
1628
1629    try:
1630        cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'a'])
1631        cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'a'])
1632        stats = cat.describe()
1633        # pandas 2.x describe() returns DataFrame with counts/freqs columns
1634        # pandasCore returns dict with count/unique/top/freq keys
1635        # Compare values logically instead of directly
1636
1637        f_print_info(f"describe() = {stats}")
1638
1639        # Verify count matches size
1640        if int(stats['count']) == cat_pd.size:
1641            f_print_success(f"count matches pandas size: {stats['count']}")
1642        else:
max (test_categorical.py:1420)
1410        # Compare min with pandas
1411        min_val = cat.min()
1412        min_val_pd = cat_pd.min()
1413        if min_val == min_val_pd:
1414            f_print_success(f"min() matches pandas: {min_val}")
1415        else:
1416            f_print_error(f"min() mismatch: pandasCore={min_val}, pandas={min_val_pd}")
1417            return False
1418
1419        # Compare max with pandas
1420        max_val = cat.max()
1421        max_val_pd = cat_pd.max()
1422        if max_val == max_val_pd:
1423            f_print_success(f"max() matches pandas: {max_val}")
1424        else:
1425            f_print_error(f"max() mismatch: pandasCore={max_val}, pandas={max_val_pd}")
1426            return False
1427
1428        # Test with unordered - should raise
1429        cat_unord = pandasCore.Categorical(['a', 'b', 'c'], ordered=False)
1430        try:
min (test_categorical.py:1411)
1401def test_min_max():
1402    """Test min and max methods (ordered only)"""
1403    f_print_header("Test: min / max")
1404
1405    try:
1406        # For ordered categorical, min/max use category order
1407        cat = pandasCore.Categorical(['b', 'a', 'c'], ordered=True)
1408        cat_pd = pd.Categorical(['b', 'a', 'c'], ordered=True)
1409
1410        # Compare min with pandas
1411        min_val = cat.min()
1412        min_val_pd = cat_pd.min()
1413        if min_val == min_val_pd:
1414            f_print_success(f"min() matches pandas: {min_val}")
1415        else:
1416            f_print_error(f"min() mismatch: pandasCore={min_val}, pandas={min_val_pd}")
1417            return False
1418
1419        # Compare max with pandas
1420        max_val = cat.max()
1421        max_val_pd = cat_pd.max()
value_counts (test_categorical.py:910)
900        return False
901
902
903def test_value_counts():
904    """Test value_counts method"""
905    f_print_header("Test: value_counts")
906
907    try:
908        cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'a', 'b'])
909        cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'a', 'b'])
910        counts = cat.value_counts()
911        counts_pd = cat_pd.value_counts()
912
913        # Compare counts with pandas
914        for val in ['a', 'b', 'c']:
915            if counts[val] == counts_pd[val]:
916                f_print_success(f"count of '{val}' matches pandas: {counts[val]}")
917            else:
918                f_print_error(f"count of '{val}' mismatch: pandasCore={counts[val]}, pandas={counts_pd[val]}")
919                return False
map (test_categorical.py:935)
925        return False
926
927
928def test_map():
929    """Test map method"""
930    f_print_header("Test: map")
931
932    try:
933        cat = pandasCore.Categorical(['a', 'b', 'c'])
934        cat_pd = pd.Categorical(['a', 'b', 'c'])
935        cat2 = cat.map({'a': 'x', 'b': 'y', 'c': 'z'})
936        cat2_pd = cat_pd.map({'a': 'x', 'b': 'y', 'c': 'z'})
937
938        # Compare mapped values with pandas
939        for i in range(len(cat2)):
940            if cat2[i] == cat2_pd[i]:
941                f_print_success(f"cat2[{i}] matches pandas: {cat2[i]}")
942            else:
943                f_print_error(f"cat2[{i}] mismatch: pandasCore={cat2[i]}, pandas={cat2_pd[i]}")
944                return False
argsort (test_categorical.py:1451)
1441        return False
1442
1443
1444def test_argsort():
1445    """Test argsort method (ordered only)"""
1446    f_print_header("Test: argsort")
1447
1448    try:
1449        cat = pandasCore.Categorical(['c', 'a', 'b'], ordered=True)
1450        cat_pd = pd.Categorical(['c', 'a', 'b'], ordered=True)
1451        indices = cat.argsort()
1452        indices_pd = list(cat_pd.argsort())
1453
1454        f_print_info(f"argsort() = {indices}")
1455        f_print_info(f"categories = {cat.categories}")
1456
1457        # Compare argsort with pandas
1458        if indices == indices_pd:
1459            f_print_success(f"argsort matches pandas: {indices}")
1460        else:
1461            f_print_error(f"argsort mismatch: pandasCore={indices}, pandas={indices_pd}")
searchsorted (test_categorical.py:1156)
1146def test_searchsorted():
1147    """Test searchsorted method"""
1148    f_print_header("Test: searchsorted")
1149
1150    try:
1151        # Must be ordered for searchsorted
1152        cat = pandasCore.Categorical(['a', 'b', 'c', 'd'], ordered=True)
1153        cat_pd = pd.Categorical(['a', 'b', 'c', 'd'], ordered=True)
1154        idx = cat.searchsorted('b')
1155        idx_pd = cat_pd.searchsorted('b')
1156
1157        # Compare searchsorted result with pandas
1158        if idx == idx_pd:
1159            f_print_success(f"searchsorted('b') matches pandas: {idx}")
1160        else:
1161            f_print_error(f"searchsorted mismatch: pandasCore={idx}, pandas={idx_pd}")
1162            return False
1163
1164        return True
sort_values (test_categorical.py:1554)
1544        return False
1545
1546
1547def test_sort_values():
1548    """Test sort_values method (ordered only)"""
1549    f_print_header("Test: sort_values (Phase 5)")
1550
1551    try:
1552        cat = pandasCore.Categorical(['c', 'a', 'b'], ordered=True)
1553        cat_pd = pd.Categorical(['c', 'a', 'b'], ordered=True)
1554        sorted_cat = cat.sort_values()
1555        sorted_cat_pd = cat_pd.sort_values()
1556
1557        f_print_info(f"original categories = {cat.categories}")
1558        f_print_info(f"sorted values = {sorted_cat.to_list()}")
1559
1560        # Compare sort_values with pandas
1561        if sorted_cat.to_list() == list(sorted_cat_pd):
1562            f_print_success(f"sort_values() matches pandas: {sorted_cat.to_list()}")
1563        else:
1564            f_print_error(f"sort_values() mismatch: pandasCore={sorted_cat.to_list()}, pandas={list(sorted_cat_pd)}")
swapaxes (test_categorical.py:2135)
2125def test_swapaxes():
2126    """Test swapaxes method"""
2127    f_print_header("Test: swapaxes (Phase 7)")
2128
2129    try:
2130        cat = pandasCore.Categorical(['a', 'b', 'c'])
2131        cat_pd = pd.Categorical(['a', 'b', 'c'])
2132
2133        # swapaxes(0, 0) should work (returns copy)
2134        swapped = cat.swapaxes(0, 0)
2135        swapped_pd = cat_pd.swapaxes(0, 0)
2136        if swapped.size == swapped_pd.size:
2137            f_print_success(f"swapaxes(0, 0) size matches pandas: {swapped.size}")
2138        else:
2139            f_print_error(f"swapaxes(0, 0) size mismatch: pandasCore={swapped.size}, pandas={swapped_pd.size}")
2140            return False
2141
2142        # Test values match pandas
2143        if swapped.to_list() == list(swapped_pd):
2144            f_print_success("swapaxes(0, 0) values match pandas")
transpose (test_categorical.py:2096)
2086def test_transpose():
2087    """Test transpose method"""
2088    f_print_header("Test: transpose (Phase 7)")
2089
2090    try:
2091        cat = pandasCore.Categorical(['a', 'b', 'c'])
2092        cat_pd = pd.Categorical(['a', 'b', 'c'])
2093
2094        # transpose is no-op for 1-D (returns copy)
2095        transposed = cat.transpose()
2096        transposed_pd = cat_pd.T
2097        if transposed.size == transposed_pd.size:
2098            f_print_success(f"transpose() size matches pandas: {transposed.size}")
2099        else:
2100            f_print_error(f"transpose() size mismatch: pandasCore={transposed.size}, pandas={transposed_pd.size}")
2101            return False
2102
2103        # Test values match pandas
2104        if transposed.to_list() == list(transposed_pd):
2105            f_print_success("transpose() values match pandas")
shift (test_categorical.py:1180)
1170        return False
1171
1172
1173def test_shift():
1174    """Test shift method"""
1175    f_print_header("Test: shift")
1176
1177    try:
1178        cat = pandasCore.Categorical(['a', 'b', 'c', 'd'])
1179        cat_pd = pd.Categorical(['a', 'b', 'c', 'd'])
1180        cat2 = cat.shift(1)
1181        cat2_pd = cat_pd.shift(1)
1182
1183        # Compare shift size with pandas
1184        if cat2.size == cat2_pd.size:
1185            f_print_success(f"shift size matches pandas: {cat2.size}")
1186        else:
1187            f_print_error(f"shift size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}")
1188            return False
1189
1190        # Compare shift codes with pandas
to_list (test_categorical.py:1600)
1590def test_to_list():
1591    """Test to_list method"""
1592    f_print_header("Test: to_list")
1593
1594    try:
1595        import numpy as np
1596        cat = pandasCore.Categorical(['a', None, 'b', 'c'])
1597        cat_pd = pd.Categorical(['a', np.nan, 'b', 'c'])
1598        lst = cat.to_list()
1599        lst_pd = cat_pd.tolist()
1600
1601        # Compare lengths
1602        if len(lst) == len(lst_pd):
1603            f_print_success(f"to_list() length matches pandas: {len(lst)}")
1604        else:
1605            f_print_error(f"to_list() length mismatch: pandasCore={len(lst)}, pandas={len(lst_pd)}")
1606            return False
1607
1608        # Compare non-NA values
to_numpy (test_categorical.py:1751)
1741def test_to_numpy():
1742    """Test to_numpy method"""
1743    f_print_header("Test: to_numpy (Phase 6)")
1744
1745    try:
1746        import numpy as np
1747
1748        cat = pandasCore.Categorical(['a', 'b', 'c', 'a'])
1749        cat_pd = pd.Categorical(['a', 'b', 'c', 'a'])
1750        arr = cat.to_numpy()
1751        arr_pd = cat_pd.codes  # pandas to_numpy returns actual values, but we return codes
1752
1753        # to_numpy returns codes as numpy array
1754        if isinstance(arr, np.ndarray):
1755            f_print_success(f"to_numpy returns numpy.ndarray")
1756        else:
1757            f_print_error(f"to_numpy should return numpy.ndarray, got {type(arr)}")
1758            return False
1759
1760        # Compare length with pandas codes
tolist (test_categorical.py:1718)
1708# Phase 6: Conversion & Output Methods
1709# =============================================================================
1710
1711def test_tolist():
1712    """Test tolist method (alias for to_list)"""
1713    f_print_header("Test: tolist (Phase 6)")
1714
1715    try:
1716        cat = pandasCore.Categorical(['a', 'b', 'c'])
1717        cat_pd = pd.Categorical(['a', 'b', 'c'])
1718        lst = cat.tolist()
1719        lst_pd = cat_pd.tolist()
1720
1721        # Compare tolist with pandas
1722        if lst == lst_pd:
1723            f_print_success(f"tolist() matches pandas: {lst}")
1724        else:
1725            f_print_error(f"tolist() mismatch: pandasCore={lst}, pandas={lst_pd}")
1726            return False
1727
1728        # Verify tolist is same as to_list
astype (test_categorical.py:1796)
1786    """Test astype method"""
1787    f_print_header("Test: astype (Phase 6)")
1788
1789    try:
1790        import numpy as np
1791
1792        cat = pandasCore.Categorical(['a', 'b', 'c'])
1793        cat_pd = pd.Categorical(['a', 'b', 'c'])
1794
1795        # Test astype('str') and compare with pandas
1796        str_result = cat.astype('str')
1797        str_result_pd = list(cat_pd.astype('str'))
1798        if str_result == str_result_pd:
1799            f_print_success(f"astype('str') matches pandas: {str_result}")
1800        else:
1801            f_print_error(f"astype('str') mismatch: pandasCore={str_result}, pandas={str_result_pd}")
1802            return False
1803
1804        # Test astype('object') and compare with pandas
1805        obj_result = cat.astype('object')
1806        obj_result_pd = list(cat_pd.astype('object'))
copy (test_categorical.py:762)
752        return False
753
754
755def test_copy():
756    """Test copy method"""
757    f_print_header("Test: copy")
758
759    try:
760        cat = pandasCore.Categorical(['a', 'b', 'c', 'a'])
761        cat_pd = pd.Categorical(['a', 'b', 'c', 'a'])
762        cat2 = cat.copy()
763        cat2_pd = cat_pd.copy()
764
765        # Compare copy size with pandas
766        if cat2.size == cat2_pd.size:
767            f_print_success(f"copy size matches pandas: {cat2.size}")
768        else:
769            f_print_error(f"copy size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}")
770            return False
771
772        # Compare copy values with pandas
view (test_categorical.py:1919)
1909        return False
1910
1911
1912def test_view():
1913    """Test view method"""
1914    f_print_header("Test: view (Phase 6)")
1915
1916    try:
1917        cat = pandasCore.Categorical(['a', 'b', 'c'])
1918        cat_pd = pd.Categorical(['a', 'b', 'c'])
1919        v = cat.view()
1920        v_pd = cat_pd.view(cat_pd.dtype)
1921
1922        # Compare view size with pandas
1923        if v.size == v_pd.size:
1924            f_print_success(f"view() size matches pandas: {v.size}")
1925        else:
1926            f_print_error(f"view() size mismatch: pandasCore={v.size}, pandas={v_pd.size}")
1927            return False
1928
1929        # Check values match
duplicated (test_categorical.py:1879)
1869def test_duplicated():
1870    """Test duplicated method"""
1871    f_print_header("Test: duplicated (Phase 6)")
1872
1873    try:
1874        cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'b'])
1875        cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'b'])
1876
1877        # Compare duplicated(keep='first') with pandas
1878        dup_first = cat.duplicated()
1879        dup_first_pd = list(cat_pd.duplicated())
1880        if dup_first == dup_first_pd:
1881            f_print_success(f"duplicated(keep='first') matches pandas: {dup_first}")
1882        else:
1883            f_print_error(f"duplicated(keep='first') mismatch: pandasCore={dup_first}, pandas={dup_first_pd}")
1884            return False
1885
1886        # Compare duplicated(keep='last') with pandas
1887        dup_last = cat.duplicated(keep='last')
1888        dup_last_pd = list(cat_pd.duplicated(keep='last'))
isin (test_categorical.py:1118)
1108        return False
1109
1110
1111def test_isin():
1112    """Test isin method"""
1113    f_print_header("Test: isin")
1114
1115    try:
1116        cat = pandasCore.Categorical(['a', 'b', 'c', 'd', 'e'])
1117        cat_pd = pd.Categorical(['a', 'b', 'c', 'd', 'e'])
1118        result = cat.isin(['a', 'c', 'e'])
1119        result_pd = list(cat_pd.isin(['a', 'c', 'e']))
1120
1121        # Compare isin result with pandas
1122        if result == result_pd:
1123            f_print_success(f"isin matches pandas: {result}")
1124        else:
1125            f_print_error(f"isin mismatch: pandasCore={result}, pandas={result_pd}")
1126            return False
1127
1128        # Test with NA values
unique (test_categorical.py:843)
833        return False
834
835
836def test_unique():
837    """Test unique method"""
838    f_print_header("Test: unique")
839
840    try:
841        cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'b', 'a'])
842        cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'b', 'a'])
843        uniq = cat.unique()
844        uniq_pd = cat_pd.unique()
845
846        # Compare unique count with pandas
847        if uniq.size == uniq_pd.size:
848            f_print_success(f"unique count matches pandas: {uniq.size}")
849        else:
850            f_print_error(f"unique count mismatch: pandasCore={uniq.size}, pandas={uniq_pd.size}")
851            return False
852
853        # Compare unique values with pandas (order may vary, use set)
add_categories (test_cat_accessor.py:33)
23    assert len(codes) == 5, f"codes length: {len(codes)}"
24
25    # ordered
26    assert s.cat.ordered == False, f"ordered: {s.cat.ordered}"
27
28def test_cat_add_categories():
29    """Test add_categories method"""
30    global tests_run
31    tests_run += 1
32    s = pandasCore.StringSeries(['a', 'b', 'c'])
33    result = s.cat.add_categories(['d', 'e'])
34    assert 'd' in result, f"add_categories result: {result}"
35    assert 'e' in result
36
37def test_cat_remove_categories():
38    """Test remove_categories method"""
39    global tests_run
40    tests_run += 1
41    s = pandasCore.StringSeries(['a', 'b', 'c'])
42    result = s.cat.remove_categories(['c'])
43    assert 'c' not in result, f"remove_categories result: {result}"
as_ordered (test_cat_accessor.py:112)
102    # With rename=True
103    result3 = s.cat.set_categories(['1', '2', '3'], rename=True)
104    assert result3 == ['1', '2', '3'], f"set_categories rename: {result3}"
105
106def test_cat_as_ordered():
107    """Test as_ordered method"""
108    global tests_run
109    tests_run += 1
110    s = pandasCore.StringSeries(['a', 'b', 'c'])
111    result = s.cat.as_ordered()
112    assert result.ordered == True, f"as_ordered: {result.ordered}"
113
114def test_cat_as_unordered():
115    """Test as_unordered method"""
116    global tests_run
117    tests_run += 1
118    s = pandasCore.StringSeries(['a', 'b', 'c'])
119    ordered_cat = s.cat.as_ordered()
120    result = ordered_cat.as_unordered()
121    assert result.ordered == False, f"as_unordered: {result.ordered}"
as_unordered (test_categorical_accessor_comp.py:252)
242    ctx.assert_false(pc_series.cat.ordered, "pc initially unordered")
243    pc_result = pc_series.cat.as_ordered()
244    # as_ordered returns a CategoricalAccessor with ordered=True
245    pc_ordered = pc_result.ordered
246
247    ctx.assert_equal(pd_ordered, pc_ordered, "as_ordered()")
248    ctx.assert_true(pc_ordered, "as_ordered result is True")
249
250
251def test_cat_as_unordered():
252    """Test .cat.as_unordered() method"""
253    f_print_header("Test: .cat.as_unordered()")
254
255    # pandas
256    pd_cat = pd.Categorical(['a', 'b', 'c'], ordered=True)
257    pd_series = pd.Series(pd_cat)
258    ctx.assert_true(pd_series.cat.ordered, "pd initially ordered")
259    pd_result = pd_series.cat.as_unordered()
260    pd_ordered = pd_result.cat.ordered
261
262    # pandasCore - first make it ordered, then unordered
remove_categories (test_cat_accessor.py:42)
32    s = pandasCore.StringSeries(['a', 'b', 'c'])
33    result = s.cat.add_categories(['d', 'e'])
34    assert 'd' in result, f"add_categories result: {result}"
35    assert 'e' in result
36
37def test_cat_remove_categories():
38    """Test remove_categories method"""
39    global tests_run
40    tests_run += 1
41    s = pandasCore.StringSeries(['a', 'b', 'c'])
42    result = s.cat.remove_categories(['c'])
43    assert 'c' not in result, f"remove_categories result: {result}"
44    assert 'a' in result
45    assert 'b' in result
46
47def test_cat_remove_unused_categories():
48    """Test remove_unused_categories method"""
49    global tests_run
50    tests_run += 1
51    s = pandasCore.StringSeries(['a', 'a', 'b'])  # Only 'a' and 'b' are used
52    result = s.cat.remove_unused_categories()
remove_unused_categories (test_cat_accessor.py:52)
42    result = s.cat.remove_categories(['c'])
43    assert 'c' not in result, f"remove_categories result: {result}"
44    assert 'a' in result
45    assert 'b' in result
46
47def test_cat_remove_unused_categories():
48    """Test remove_unused_categories method"""
49    global tests_run
50    tests_run += 1
51    s = pandasCore.StringSeries(['a', 'a', 'b'])  # Only 'a' and 'b' are used
52    result = s.cat.remove_unused_categories()
53    assert len(result) == 2, f"remove_unused_categories: {result}"
54
55def test_cat_rename_categories_list():
56    """Test rename_categories with list"""
57    global tests_run
58    tests_run += 1
59    s = pandasCore.StringSeries(['a', 'b', 'c'])
60    result = s.cat.rename_categories(['x', 'y', 'z'])
61    assert result == ['x', 'y', 'z'], f"rename_categories (list): {result}"
rename_categories (test_cat_accessor.py:60)
50    tests_run += 1
51    s = pandasCore.StringSeries(['a', 'a', 'b'])  # Only 'a' and 'b' are used
52    result = s.cat.remove_unused_categories()
53    assert len(result) == 2, f"remove_unused_categories: {result}"
54
55def test_cat_rename_categories_list():
56    """Test rename_categories with list"""
57    global tests_run
58    tests_run += 1
59    s = pandasCore.StringSeries(['a', 'b', 'c'])
60    result = s.cat.rename_categories(['x', 'y', 'z'])
61    assert result == ['x', 'y', 'z'], f"rename_categories (list): {result}"
62
63def test_cat_rename_categories_dict():
64    """Test rename_categories with dict"""
65    global tests_run
66    tests_run += 1
67    s = pandasCore.StringSeries(['a', 'b', 'c'])
68    result = s.cat.rename_categories({'a': 'alpha', 'b': 'beta'})
69    assert 'alpha' in result, f"rename_categories (dict): {result}"
70    assert 'beta' in result
reorder_categories (test_cat_accessor.py:78)
68    result = s.cat.rename_categories({'a': 'alpha', 'b': 'beta'})
69    assert 'alpha' in result, f"rename_categories (dict): {result}"
70    assert 'beta' in result
71    assert 'c' in result  # Unchanged
72
73def test_cat_reorder_categories():
74    """Test reorder_categories method"""
75    global tests_run
76    tests_run += 1
77    s = pandasCore.StringSeries(['a', 'b', 'c'])
78    result = s.cat.reorder_categories(['c', 'b', 'a'])
79    assert result == ['c', 'b', 'a'], f"reorder_categories: {result}"
80
81def test_cat_reorder_categories_ordered():
82    """Test reorder_categories with ordered parameter"""
83    global tests_run
84    tests_run += 1
85    s = pandasCore.StringSeries(['a', 'b', 'c'])
86    result = s.cat.reorder_categories(['c', 'b', 'a'], ordered=True)
87    assert result == ['c', 'b', 'a'], f"reorder_categories ordered: {result}"
set_categories (test_cat_accessor.py:96)
 86    result = s.cat.reorder_categories(['c', 'b', 'a'], ordered=True)
 87    assert result == ['c', 'b', 'a'], f"reorder_categories ordered: {result}"
 88
 89def test_cat_set_categories():
 90    """Test set_categories method"""
 91    global tests_run
 92    tests_run += 1
 93    s = pandasCore.StringSeries(['a', 'b', 'c'])
 94
 95    # Default: ordered=False, rename=False
 96    result = s.cat.set_categories(['x', 'y', 'z'])
 97    assert result == ['x', 'y', 'z'], f"set_categories default: {result}"
 98
 99    # With ordered=True
100    result2 = s.cat.set_categories(['p', 'q', 'r'], ordered=True)
101    assert result2 == ['p', 'q', 'r'], f"set_categories ordered: {result2}"
102
103    # With rename=True
104    result3 = s.cat.set_categories(['1', '2', '3'], rename=True)
105    assert result3 == ['1', '2', '3'], f"set_categories rename: {result3}"
argmax (test_categorical.py:1518)
1508        return False
1509
1510
1511def test_argmax():
1512    """Test argmax method (ordered only)"""
1513    f_print_header("Test: argmax (Phase 5)")
1514
1515    try:
1516        cat = pandasCore.Categorical(['b', 'a', 'c', 'a'], ordered=True)
1517        cat_pd = pd.Categorical(['b', 'a', 'c', 'a'], ordered=True)
1518        idx = cat.argmax()
1519        idx_pd = cat_pd.argmax()
1520
1521        f_print_info(f"categories = {cat.categories}")
1522        f_print_info(f"argmax() = {idx}")
1523
1524        # Compare argmax with pandas
1525        if idx == idx_pd:
1526            f_print_success(f"argmax() matches pandas: {idx}")
1527        else:
1528            f_print_error(f"argmax() mismatch: pandasCore={idx}, pandas={idx_pd}")
argmin (test_categorical.py:1482)
1472# Phase 5: Statistics & Ordering Methods
1473# =============================================================================
1474
1475def test_argmin():
1476    """Test argmin method (ordered only)"""
1477    f_print_header("Test: argmin (Phase 5)")
1478
1479    try:
1480        cat = pandasCore.Categorical(['b', 'a', 'c', 'a'], ordered=True)
1481        cat_pd = pd.Categorical(['b', 'a', 'c', 'a'], ordered=True)
1482        idx = cat.argmin()
1483        idx_pd = cat_pd.argmin()
1484
1485        f_print_info(f"categories = {cat.categories}")
1486        f_print_info(f"argmin() = {idx}")
1487
1488        # Compare argmin with pandas
1489        if idx == idx_pd:
1490            f_print_success(f"argmin() matches pandas: {idx}")
1491        else:
1492            f_print_error(f"argmin() mismatch: pandasCore={idx}, pandas={idx_pd}")
delete (test_categorical.py:1044)
1034        return False
1035
1036
1037def test_delete():
1038    """Test delete method"""
1039    f_print_header("Test: delete")
1040
1041    try:
1042        cat = pandasCore.Categorical(['a', 'b', 'c', 'd'])
1043        cat_pd = pd.Categorical(['a', 'b', 'c', 'd'])
1044        cat2 = cat.delete(1)  # Delete 'b'
1045        cat2_pd = cat_pd.delete(1)
1046
1047        # Compare delete size with pandas
1048        if cat2.size == cat2_pd.size:
1049            f_print_success(f"delete size matches pandas: {cat2.size}")
1050        else:
1051            f_print_error(f"delete size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}")
1052            return False
1053
1054        # Compare delete values with pandas
factorize (test_categorical.py:876)
866        return False
867
868
869def test_factorize():
870    """Test factorize method"""
871    f_print_header("Test: factorize")
872
873    try:
874        cat = pandasCore.Categorical(['a', 'b', 'a', 'c'])
875        cat_pd = pd.Categorical(['a', 'b', 'a', 'c'])
876        codes, uniques = cat.factorize()
877        codes_pd, uniques_pd = cat_pd.factorize()
878
879        # Compare codes length with pandas
880        if len(codes) == len(codes_pd):
881            f_print_success(f"codes length matches pandas: {len(codes)}")
882        else:
883            f_print_error(f"codes length mismatch: pandasCore={len(codes)}, pandas={len(codes_pd)}")
884            return False
885
886        # Compare uniques count with pandas
memory_usage (test_categorical.py:1846)
1836def test_memory_usage():
1837    """Test memory_usage method"""
1838    f_print_header("Test: memory_usage (Phase 6)")
1839
1840    try:
1841        cat = pandasCore.Categorical(['a', 'b', 'c', 'a', 'b'])
1842        cat_pd = pd.Categorical(['a', 'b', 'c', 'a', 'b'])
1843
1844        # Basic memory_usage - both should be positive
1845        mem = cat.memory_usage()
1846        mem_pd = cat_pd.memory_usage()
1847        if isinstance(mem, int) and mem > 0 and isinstance(mem_pd, int) and mem_pd > 0:
1848            f_print_success(f"memory_usage() both positive: pandasCore={mem}, pandas={mem_pd}")
1849        else:
1850            f_print_error(f"memory_usage() should be positive int: pandasCore={mem}, pandas={mem_pd}")
1851            return False
1852
1853        # memory_usage with deep=True
1854        mem_deep = cat.memory_usage(deep=True)
1855        mem_deep_pd = cat_pd.memory_usage(deep=True)
ravel (test_categorical.py:2058)
2048def test_ravel():
2049    """Test ravel method"""
2050    f_print_header("Test: ravel (Phase 7)")
2051
2052    try:
2053        cat = pandasCore.Categorical(['a', 'b', 'c'])
2054        cat_pd = pd.Categorical(['a', 'b', 'c'])
2055
2056        # ravel returns copy (already 1-D)
2057        raveled = cat.ravel()
2058        raveled_pd = cat_pd.ravel()
2059        if raveled.size == raveled_pd.size:
2060            f_print_success(f"ravel() size matches pandas: {raveled.size}")
2061        else:
2062            f_print_error(f"ravel() size mismatch: pandasCore={raveled.size}, pandas={raveled_pd.size}")
2063            return False
2064
2065        # Test values match pandas
2066        if raveled.to_list() == list(raveled_pd):
2067            f_print_success("ravel() values match pandas")
repeat (test_categorical.py:1963)
1953def test_repeat():
1954    """Test repeat method"""
1955    f_print_header("Test: repeat (Phase 7)")
1956
1957    try:
1958        cat = pandasCore.Categorical(['a', 'b', 'c'])
1959        cat_pd = pd.Categorical(['a', 'b', 'c'])
1960
1961        # Compare repeat(2) with pandas
1962        repeated = cat.repeat(2)
1963        repeated_pd = cat_pd.repeat(2)
1964        if repeated.to_list() == list(repeated_pd):
1965            f_print_success(f"repeat(2) matches pandas: {repeated.to_list()}")
1966        else:
1967            f_print_error(f"repeat(2) mismatch: pandasCore={repeated.to_list()}, pandas={list(repeated_pd)}")
1968            return False
1969
1970        # Compare size with pandas
1971        if repeated.size == repeated_pd.size:
1972            f_print_success(f"repeat(2) size matches pandas: {repeated.size}")
reshape (test_categorical.py:2020)
2010def test_reshape():
2011    """Test reshape method"""
2012    f_print_header("Test: reshape (Phase 7)")
2013
2014    try:
2015        cat = pandasCore.Categorical(['a', 'b', 'c'])
2016        cat_pd = pd.Categorical(['a', 'b', 'c'])
2017
2018        # Compare reshape(-1) with pandas (pandas uses codes reshape)
2019        reshaped = cat.reshape(-1)
2020        if reshaped.size == cat_pd.size:
2021            f_print_success(f"reshape(-1) size matches original: {reshaped.size}")
2022        else:
2023            f_print_error(f"reshape(-1) size wrong: {reshaped.size}, expected {cat_pd.size}")
2024            return False
2025
2026        # Test values preserved
2027        if reshaped.to_list() == list(cat_pd):
2028            f_print_success("reshape(-1) values match pandas")
2029        else:
set_ordered (test_categorical.py:638)
628def test_set_ordered():
629    """Test set_ordered method"""
630    f_print_header("Test: set_ordered")
631
632    try:
633        cat = pandasCore.Categorical(['a', 'b', 'c'])
634        cat_pd = pd.Categorical(['a', 'b', 'c'])
635
636        # Set to ordered
637        cat_ord = cat.set_ordered(True)
638        cat_ord_pd = cat_pd.set_ordered(True)
639        if cat_ord.ordered == cat_ord_pd.ordered:
640            f_print_success(f"set_ordered(True) matches pandas: {cat_ord.ordered}")
641        else:
642            f_print_error(f"set_ordered(True) mismatch: pandasCore={cat_ord.ordered}, pandas={cat_ord_pd.ordered}")
643            return False
644
645        # Set back to unordered
646        cat_unord = cat_ord.set_ordered(False)
647        cat_unord_pd = cat_ord_pd.set_ordered(False)