Categorical =========== .. currentmodule:: pandasCore .. class:: Categorical Represent a categorical variable in pandas. Example ------- .. code-block:: python import pandasCore as pd # Create Categorical obj = pd.Categorical(...) Attributes ---------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Attribute - Description - Example * - :attr:`~Categorical.T` - Return transposed Categorical (alias for transpose()). - :ref:`View ` * - :attr:`~Categorical.categories` - The categories of this categorical - :ref:`View ` * - :attr:`~Categorical.codes` - The category codes of this categorical - :ref:`View ` * - :attr:`~Categorical.empty` - Whether the array is empty - :ref:`View ` * - :attr:`~Categorical.nbytes` - Memory usage in bytes - :ref:`View ` * - :attr:`~Categorical.ndim` - Number of dimensions (always 1) - :ref:`View ` * - :attr:`~Categorical.ordered` - Whether the categorical is ordered - :ref:`View ` * - :attr:`~Categorical.shape` - Shape of the array - :ref:`View ` * - :attr:`~Categorical.size` - Number of elements - :ref:`View ` Construction ------------ .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.__init__` ``(*args, **kwargs) | () | (values: list, categories: object = None, ordered: object = None, dtype: object = None, fastpath: object = None, copy: bool = True)`` - Create an empty Categorical - :ref:`View ` Indexing / Selection -------------------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.__getitem__` ``(idx: typing.SupportsInt)`` - Get element by position - * - :meth:`~Categorical.take` ``(indices: collections.abc.Sequence[typing.SupportsInt], *, allow_fill: bool = False, fill_value: object = None, axis: typing.SupportsInt = 0)`` - Take elements from the Categorical. - :ref:`View ` Data Manipulation ----------------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.insert` ``(loc: typing.SupportsInt, item: object)`` - Insert element at position. - :ref:`View ` Missing Data ------------ .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.dropna` ``()`` - Return Categorical without NA values. - :ref:`View ` * - :meth:`~Categorical.fillna` ``(value: object = None, method: object = None, limit: object = None, copy: bool = True)`` - Fill NA/NaN values using the specified value. - :ref:`View ` * - :meth:`~Categorical.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. - :ref:`View ` * - :meth:`~Categorical.isna` ``()`` - Detect missing values. - :ref:`View ` * - :meth:`~Categorical.isnull` ``()`` - Detect missing values (alias for isna). - :ref:`View ` * - :meth:`~Categorical.notna` ``()`` - Detect existing (non-missing) values. - :ref:`View ` * - :meth:`~Categorical.notnull` ``()`` - Detect existing (non-missing) values (alias for notna). - :ref:`View ` Statistics ---------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.describe` ``()`` - Generate descriptive statistics. - :ref:`View ` * - :meth:`~Categorical.max` ``(*, skipna: bool = True, **kwargs)`` - Return the maximum value. - :ref:`View ` * - :meth:`~Categorical.min` ``(*, skipna: bool = True, **kwargs)`` - Return the minimum value. - :ref:`View ` * - :meth:`~Categorical.value_counts` ``(dropna: bool = True)`` - Return a dict containing counts of unique values. - :ref:`View ` Aggregation ----------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.map` ``(mapper: object, na_action: object = None)`` - Map values using input dict. - :ref:`View ` Comparison ---------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.__eq__` ``(self, value, /)`` - Return self==value. - * - :meth:`~Categorical.__ge__` ``(self, value, /)`` - Return self>=value. - * - :meth:`~Categorical.__gt__` ``(self, value, /)`` - Return self>value. - * - :meth:`~Categorical.__le__` ``(self, value, /)`` - Return self<=value. - * - :meth:`~Categorical.__lt__` ``(self, value, /)`` - Return self` * - :meth:`~Categorical.searchsorted` ``(value: object, side: str = 'left', sorter: object = None)`` - Find indices where elements should be inserted to maintain order. - :ref:`View ` * - :meth:`~Categorical.sort_values` ``(*, inplace: bool = False, ascending: bool = True, na_position: str = 'last')`` - Sort by the values. - :ref:`View ` Reshaping --------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.swapaxes` ``(axis1: typing.SupportsInt, axis2: typing.SupportsInt)`` - Interchange axes of the Categorical. - :ref:`View ` * - :meth:`~Categorical.transpose` ``(*args)`` - Return transposed Categorical. - :ref:`View ` Time Series ----------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.shift` ``(periods: typing.SupportsInt = 1, fill_value: object = None)`` - Shift values by desired number of periods. - :ref:`View ` I/O --- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.to_list` ``()`` - Return a list of the values. - :ref:`View ` * - :meth:`~Categorical.to_numpy` ``(dtype: object = None, copy: bool = False, na_value: object = None)`` - Return a NumPy array of the values (codes). - :ref:`View ` * - :meth:`~Categorical.tolist` ``()`` - Return a list of the values. - :ref:`View ` Conversion ---------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.astype` ``(dtype: object, copy: bool = True)`` - Cast to a specified dtype. - :ref:`View ` * - :meth:`~Categorical.copy` ``(order: str = 'C')`` - Return a copy of the Categorical. - :ref:`View ` * - :meth:`~Categorical.view` ``(dtype: object = None)`` - Return a view on the array. - :ref:`View ` Iteration --------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.__len__` ``()`` - Return the number of elements - Set Operations -------------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.duplicated` ``(keep: str = 'first')`` - Indicate duplicate values. - :ref:`View ` * - :meth:`~Categorical.isin` ``(values: collections.abc.Sequence[str])`` - Check whether values are contained in Categorical. - :ref:`View ` * - :meth:`~Categorical.unique` ``()`` - Return unique values. - :ref:`View ` Categorical Methods ------------------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.add_categories` ``(new_categories: collections.abc.Sequence[str])`` - Add new categories. - :ref:`View ` * - :meth:`~Categorical.as_ordered` ``()`` - Set the Categorical to be ordered. - :ref:`View ` * - :meth:`~Categorical.as_unordered` ``()`` - Set the Categorical to be unordered. - :ref:`View ` * - :meth:`~Categorical.remove_categories` ``(removals: collections.abc.Sequence[str])`` - Remove the specified categories. - :ref:`View ` * - :meth:`~Categorical.remove_unused_categories` ``()`` - Remove categories which are not used. - :ref:`View ` * - :meth:`~Categorical.rename_categories` ``(new_categories: collections.abc.Sequence[str])`` - Rename categories. - :ref:`View ` * - :meth:`~Categorical.reorder_categories` ``(new_categories: collections.abc.Sequence[str], ordered: bool | None = None)`` - Reorder categories as specified in new_categories. - :ref:`View ` * - :meth:`~Categorical.set_categories` ``(new_categories: collections.abc.Sequence[str], ordered: bool | None = None, rename: bool = False)`` - Set the categories to the specified new_categories. - :ref:`View ` Other Methods ------------- .. list-table:: :widths: 25 60 15 :header-rows: 1 * - Method - Description - Example * - :meth:`~Categorical.__hash__` ``(self, /)`` - Return hash(self). - * - :meth:`~Categorical.__repr__` ``()`` - - * - :meth:`~Categorical.__str__` ``()`` - - * - :meth:`~Categorical.argmax` ``(axis: typing.SupportsInt = 0, skipna: bool = True)`` - Return the index of the maximum value. - :ref:`View ` * - :meth:`~Categorical.argmin` ``(axis: typing.SupportsInt = 0, skipna: bool = True)`` - Return the index of the minimum value. - :ref:`View ` * - :meth:`~Categorical.check_for_ordered` ``(op: str)`` - Assert that the Categorical is ordered. - * - :meth:`~Categorical.delete` ``(loc: object, axis: typing.SupportsInt = 0)`` - Delete element at position. - :ref:`View ` * - :meth:`~Categorical.factorize` ``(use_na_sentinel: bool = True)`` - Encode the object as an enumerated type. - :ref:`View ` * - :meth:`~Categorical.memory_usage` ``(deep: bool = False)`` - Return the memory usage of the Categorical. - :ref:`View ` * - :meth:`~Categorical.ravel` ``(order: str = 'C')`` - Return a flattened (1-dimensional) Categorical. - :ref:`View ` * - :meth:`~Categorical.repeat` ``(repeats: object, axis: typing.SupportsInt = 0)`` - Repeat elements of a Categorical. - :ref:`View ` * - :meth:`~Categorical.reshape` ``(shape: object)`` - Return a Categorical with the same data but a different shape. - :ref:`View ` * - :meth:`~Categorical.set_ordered` ``(value: bool)`` - Set the ordered attribute to the boolean value. - :ref:`View ` Code Examples ------------- The following examples are extracted from the test suite. .. _example-categorical-t-0: .. dropdown:: T (test_categorical.py:2112) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 2102 :emphasize-lines: 11 return False # Test values match pandas if transposed.to_list() == list(transposed_pd): f_print_success("transpose() values match pandas") else: f_print_error(f"transpose() values mismatch") return False # Test T property (alias for transpose) t_prop = cat.T if t_prop.to_list() == list(cat_pd.T): f_print_success("T property matches pandas") else: f_print_error(f"T property mismatch") return False return True except Exception as e: f_print_error(f"Exception: {e}") .. _example-categorical-categories-1: .. dropdown:: categories (test_accessor_descriptor.py:220) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 210 :emphasize-lines: 11 f_print_info(f"type(s.cat).__name__ = {type_name}") if type_name == "CategoricalAccessor": f_print_success("s.cat returns CategoricalAccessor") else: f_print_error(f"Expected CategoricalAccessor, got {type_name}") return False # Test categories property categories = cat_accessor.categories f_print_success(f"cat.categories: {categories}") return True except Exception as e: f_print_error(f"Exception: {e}") return False def test_datetime_series_dt_accessor(): """Test that DatetimeSeries.dt accessor works on instance""" .. _example-categorical-codes-2: .. dropdown:: codes (test_categorical.py:104) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 94 :emphasize-lines: 11 return False # Compare ordered with pandas if cat.ordered == cat_pd.ordered: f_print_success(f"ordered matches pandas: {cat.ordered}") else: f_print_error(f"ordered mismatch: pandasCore={cat.ordered}, pandas={cat_pd.ordered}") return False # Compare codes length with pandas if len(cat.codes) == len(cat_pd.codes): f_print_success(f"codes length matches pandas: {len(cat.codes)}") else: f_print_error(f"codes length mismatch: pandasCore={len(cat.codes)}, pandas={len(cat_pd.codes)}") return False return True except Exception as e: f_print_error(f"Exception: {e}") return False .. _example-categorical-empty-3: .. dropdown:: empty (test_categorical.py:46) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 36 :emphasize-lines: 11 # Compare size with pandas if cat.size == cat_pd.size: f_print_success(f"size matches pandas: {cat.size}") else: f_print_error(f"size mismatch: pandasCore={cat.size}, pandas={cat_pd.size}") return False # Check empty property (note: pandas Categorical doesn't have .empty, but pandasCore does) # We verify empty is True when size is 0 expected_empty = (cat_pd.size == 0) if cat.empty == expected_empty: f_print_success(f"empty property matches expected: {cat.empty}") else: f_print_error(f"empty mismatch: pandasCore={cat.empty}, expected={expected_empty}") return False # Compare ordered with pandas if cat.ordered == cat_pd.ordered: f_print_success(f"ordered matches pandas: {cat.ordered}") else: f_print_error(f"ordered mismatch: pandasCore={cat.ordered}, pandas={cat_pd.ordered}") .. _example-categorical-nbytes-4: .. dropdown:: nbytes (test_categorical.py:229) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 219 :emphasize-lines: 11 return False # Compare shape with pandas if cat.shape == cat_pd.shape: f_print_success(f"shape matches pandas: {cat.shape}") else: f_print_error(f"shape mismatch: pandasCore={cat.shape}, pandas={cat_pd.shape}") return False # Compare nbytes with pandas if cat.nbytes > 0 and cat_pd.nbytes > 0: f_print_success(f"nbytes both positive: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}") else: f_print_error(f"nbytes should be > 0: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}") return False return True except Exception as e: f_print_error(f"Exception: {e}") return False .. _example-categorical-ndim-5: .. dropdown:: ndim (test_categorical.py:215) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 205 :emphasize-lines: 11 # Check empty (pandas Categorical doesn't have .empty, compare with size==0) expected_empty = (cat_pd.size == 0) if cat.empty == expected_empty: f_print_success(f"empty matches expected: {cat.empty}") else: f_print_error(f"empty mismatch: pandasCore={cat.empty}, expected={expected_empty}") return False # Compare ndim with pandas if cat.ndim == cat_pd.ndim: f_print_success(f"ndim matches pandas: {cat.ndim}") else: f_print_error(f"ndim mismatch: pandasCore={cat.ndim}, pandas={cat_pd.ndim}") return False # Compare shape with pandas if cat.shape == cat_pd.shape: f_print_success(f"shape matches pandas: {cat.shape}") else: f_print_error(f"shape mismatch: pandasCore={cat.shape}, pandas={cat_pd.shape}") .. _example-categorical-ordered-6: .. dropdown:: ordered (test_categorical.py:53) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 43 :emphasize-lines: 11 # Check empty property (note: pandas Categorical doesn't have .empty, but pandasCore does) # We verify empty is True when size is 0 expected_empty = (cat_pd.size == 0) if cat.empty == expected_empty: f_print_success(f"empty property matches expected: {cat.empty}") else: f_print_error(f"empty mismatch: pandasCore={cat.empty}, expected={expected_empty}") return False # Compare ordered with pandas if cat.ordered == cat_pd.ordered: f_print_success(f"ordered matches pandas: {cat.ordered}") else: f_print_error(f"ordered mismatch: pandasCore={cat.ordered}, pandas={cat_pd.ordered}") return False # Compare categories with pandas if len(cat.categories) == len(cat_pd.categories): f_print_success(f"categories length matches pandas: {len(cat.categories)}") else: f_print_error(f"categories mismatch: pandasCore={cat.categories}, pandas={list(cat_pd.categories)}") .. _example-categorical-shape-7: .. dropdown:: shape (test_categorical.py:222) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 212 :emphasize-lines: 11 return False # Compare ndim with pandas if cat.ndim == cat_pd.ndim: f_print_success(f"ndim matches pandas: {cat.ndim}") else: f_print_error(f"ndim mismatch: pandasCore={cat.ndim}, pandas={cat_pd.ndim}") return False # Compare shape with pandas if cat.shape == cat_pd.shape: f_print_success(f"shape matches pandas: {cat.shape}") else: f_print_error(f"shape mismatch: pandasCore={cat.shape}, pandas={cat_pd.shape}") return False # Compare nbytes with pandas if cat.nbytes > 0 and cat_pd.nbytes > 0: f_print_success(f"nbytes both positive: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}") else: f_print_error(f"nbytes should be > 0: pandasCore={cat.nbytes}, pandas={cat_pd.nbytes}") .. _example-categorical-size-8: .. dropdown:: size (test_categorical.py:37) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 27 :emphasize-lines: 11 def test_empty_categorical(): """Test empty Categorical constructor""" f_print_header("Test: Empty Categorical") try: cat = pandasCore.Categorical() cat_pd = pd.Categorical([]) f_print_success("Created empty Categorical") # Compare size with pandas if cat.size == cat_pd.size: f_print_success(f"size matches pandas: {cat.size}") else: f_print_error(f"size mismatch: pandasCore={cat.size}, pandas={cat_pd.size}") return False # Check empty property (note: pandas Categorical doesn't have .empty, but pandasCore does) # We verify empty is True when size is 0 expected_empty = (cat_pd.size == 0) if cat.empty == expected_empty: f_print_success(f"empty property matches expected: {cat.empty}") .. _example-categorical-dunder-initdunder--9: .. dropdown:: __init__ (test_categorical.py:32) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 22 :emphasize-lines: 11 # Direct imports import pandasCore import pandas as pd def test_empty_categorical(): """Test empty Categorical constructor""" f_print_header("Test: Empty Categorical") try: cat = pandasCore.Categorical() cat_pd = pd.Categorical([]) f_print_success("Created empty Categorical") # Compare size with pandas if cat.size == cat_pd.size: f_print_success(f"size matches pandas: {cat.size}") else: f_print_error(f"size mismatch: pandasCore={cat.size}, pandas={cat_pd.size}") return False .. _example-categorical-take-10: .. dropdown:: take (test_categorical.py:802) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 792 :emphasize-lines: 11 return False def test_take(): """Test take method""" f_print_header("Test: take") try: cat = pandasCore.Categorical(['a', 'b', 'c', 'd', 'e']) cat_pd = pd.Categorical(['a', 'b', 'c', 'd', 'e']) cat2 = cat.take([0, 2, 4]) cat2_pd = cat_pd.take([0, 2, 4]) # Compare take size with pandas if cat2.size == cat2_pd.size: f_print_success(f"take size matches pandas: {cat2.size}") else: f_print_error(f"take size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}") return False # Compare take values with pandas .. _example-categorical-insert-11: .. dropdown:: insert (test_categorical.py:1077) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1067 :emphasize-lines: 11 def test_insert(): """Test insert method""" f_print_header("Test: insert") try: import numpy as np cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) cat2 = cat.insert(1, 'b') # Insert 'b' at index 1 (must be existing category) cat2_pd = cat_pd.insert(1, 'b') # Compare insert size with pandas if cat2.size == cat2_pd.size: f_print_success(f"insert size matches pandas: {cat2.size}") else: f_print_error(f"insert size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}") return False # Compare insert values with pandas .. _example-categorical-dropna-12: .. dropdown:: dropna (test_categorical.py:1012) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1002 :emphasize-lines: 11 def test_dropna(): """Test dropna method""" f_print_header("Test: dropna") try: import numpy as np cat = pandasCore.Categorical(['a', None, 'b', None, 'c']) cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan, 'c']) cat2 = cat.dropna() cat2_pd = cat_pd.dropna() # Compare dropna size with pandas if cat2.size == cat2_pd.size: f_print_success(f"dropna size matches pandas: {cat2.size}") else: f_print_error(f"dropna size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}") return False # Compare values with pandas .. _example-categorical-fillna-13: .. dropdown:: fillna (test_categorical.py:974) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 964 :emphasize-lines: 11 def test_fillna(): """Test fillna method""" f_print_header("Test: fillna") try: import numpy as np # fillna requires value to be in categories - use an existing category cat = pandasCore.Categorical(['a', None, 'b', None]) cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan]) cat2 = cat.fillna('a') # Use 'a' which is in categories cat2_pd = cat_pd.fillna('a') # Compare fillna result with pandas for i in range(len(cat2)): if cat2[i] == cat2_pd[i]: f_print_success(f"fillna cat2[{i}] matches pandas: {cat2[i]}") else: f_print_error(f"fillna cat2[{i}] mismatch: pandasCore={cat2[i]}, pandas={cat2_pd[i]}") return False .. _example-categorical-interpolate-14: .. dropdown:: interpolate (test_categorical.py:1224) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1214 :emphasize-lines: 11 """Test interpolate method with full pandas 2.x compatible parameters""" f_print_header("Test: interpolate") try: import numpy as np # Test data: NA, a, NA, NA, b, NA cat = pandasCore.Categorical([None, 'a', None, None, 'b', None]) # Test 1: Basic forward fill (default) cat_ffill = cat.interpolate(method='ffill') expected_ffill = [None, 'a', 'a', 'a', 'b', 'b'] result_ffill = cat_ffill.tolist() if result_ffill == expected_ffill: f_print_success(f"interpolate ffill: {result_ffill}") else: f_print_error(f"interpolate ffill mismatch: got {result_ffill}, expected {expected_ffill}") return False # Test 2: Backward fill cat_bfill = cat.interpolate(method='bfill') .. _example-categorical-isna-15: .. dropdown:: isna (test_categorical.py:1333) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1323 :emphasize-lines: 11 def test_isna_notna(): """Test isna and notna methods""" f_print_header("Test: isna / notna") try: import numpy as np cat = pandasCore.Categorical(['a', None, 'b', None]) cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan]) isna_result = cat.isna() isna_result_pd = list(cat_pd.isna()) if isna_result == isna_result_pd: f_print_success(f"isna() matches pandas: {isna_result}") else: f_print_error(f"isna() mismatch: pandasCore={isna_result}, pandas={isna_result_pd}") return False notna_result = cat.notna() notna_result_pd = list(cat_pd.notna()) if notna_result == notna_result_pd: .. _example-categorical-isnull-16: .. dropdown:: isnull (test_categorical.py:1366) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1356 :emphasize-lines: 11 def test_isnull_notnull(): """Test isnull and notnull methods (aliases for isna/notna)""" f_print_header("Test: isnull / notnull (Phase 4)") try: import numpy as np cat = pandasCore.Categorical(['a', None, 'b', None, 'c']) cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan, 'c']) # Compare isnull with pandas isnull_result = cat.isnull() isnull_result_pd = list(cat_pd.isnull()) if isnull_result == isnull_result_pd: f_print_success(f"isnull() matches pandas: {isnull_result}") else: f_print_error(f"isnull() mismatch: pandasCore={isnull_result}, pandas={isnull_result_pd}") return False # Compare notnull with pandas notnull_result = cat.notnull() notnull_result_pd = list(cat_pd.notnull()) .. _example-categorical-notna-17: .. dropdown:: notna (test_categorical.py:1341) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1331 :emphasize-lines: 11 cat_pd = pd.Categorical(['a', np.nan, 'b', np.nan]) isna_result = cat.isna() isna_result_pd = list(cat_pd.isna()) if isna_result == isna_result_pd: f_print_success(f"isna() matches pandas: {isna_result}") else: f_print_error(f"isna() mismatch: pandasCore={isna_result}, pandas={isna_result_pd}") return False notna_result = cat.notna() notna_result_pd = list(cat_pd.notna()) if notna_result == notna_result_pd: f_print_success(f"notna() matches pandas: {notna_result}") else: f_print_error(f"notna() mismatch: pandasCore={notna_result}, pandas={notna_result_pd}") return False return True except Exception as e: .. _example-categorical-notnull-18: .. dropdown:: notnull (test_categorical.py:1375) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1365 :emphasize-lines: 11 # Compare isnull with pandas isnull_result = cat.isnull() isnull_result_pd = list(cat_pd.isnull()) if isnull_result == isnull_result_pd: f_print_success(f"isnull() matches pandas: {isnull_result}") else: f_print_error(f"isnull() mismatch: pandasCore={isnull_result}, pandas={isnull_result_pd}") return False # Compare notnull with pandas notnull_result = cat.notnull() notnull_result_pd = list(cat_pd.notnull()) if notnull_result == notnull_result_pd: f_print_success(f"notnull() matches pandas: {notnull_result}") else: f_print_error(f"notnull() mismatch: pandasCore={notnull_result}, pandas={notnull_result_pd}") return False # Verify isna and notna are inverses isna_result = cat.isna() notna_result = cat.notna() .. _example-categorical-describe-19: .. dropdown:: describe (test_categorical.py:1632) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1622 :emphasize-lines: 11 return False def test_describe(): """Test describe method""" f_print_header("Test: describe") try: cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'a']) cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'a']) stats = cat.describe() # pandas 2.x describe() returns DataFrame with counts/freqs columns # pandasCore returns dict with count/unique/top/freq keys # Compare values logically instead of directly f_print_info(f"describe() = {stats}") # Verify count matches size if int(stats['count']) == cat_pd.size: f_print_success(f"count matches pandas size: {stats['count']}") else: .. _example-categorical-max-20: .. dropdown:: max (test_categorical.py:1420) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1410 :emphasize-lines: 11 # Compare min with pandas min_val = cat.min() min_val_pd = cat_pd.min() if min_val == min_val_pd: f_print_success(f"min() matches pandas: {min_val}") else: f_print_error(f"min() mismatch: pandasCore={min_val}, pandas={min_val_pd}") return False # Compare max with pandas max_val = cat.max() max_val_pd = cat_pd.max() if max_val == max_val_pd: f_print_success(f"max() matches pandas: {max_val}") else: f_print_error(f"max() mismatch: pandasCore={max_val}, pandas={max_val_pd}") return False # Test with unordered - should raise cat_unord = pandasCore.Categorical(['a', 'b', 'c'], ordered=False) try: .. _example-categorical-min-21: .. dropdown:: min (test_categorical.py:1411) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1401 :emphasize-lines: 11 def test_min_max(): """Test min and max methods (ordered only)""" f_print_header("Test: min / max") try: # For ordered categorical, min/max use category order cat = pandasCore.Categorical(['b', 'a', 'c'], ordered=True) cat_pd = pd.Categorical(['b', 'a', 'c'], ordered=True) # Compare min with pandas min_val = cat.min() min_val_pd = cat_pd.min() if min_val == min_val_pd: f_print_success(f"min() matches pandas: {min_val}") else: f_print_error(f"min() mismatch: pandasCore={min_val}, pandas={min_val_pd}") return False # Compare max with pandas max_val = cat.max() max_val_pd = cat_pd.max() .. _example-categorical-value_counts-22: .. dropdown:: value_counts (test_categorical.py:910) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 900 :emphasize-lines: 11 return False def test_value_counts(): """Test value_counts method""" f_print_header("Test: value_counts") try: cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'a', 'b']) cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'a', 'b']) counts = cat.value_counts() counts_pd = cat_pd.value_counts() # Compare counts with pandas for val in ['a', 'b', 'c']: if counts[val] == counts_pd[val]: f_print_success(f"count of '{val}' matches pandas: {counts[val]}") else: f_print_error(f"count of '{val}' mismatch: pandasCore={counts[val]}, pandas={counts_pd[val]}") return False .. _example-categorical-map-23: .. dropdown:: map (test_categorical.py:935) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 925 :emphasize-lines: 11 return False def test_map(): """Test map method""" f_print_header("Test: map") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) cat2 = cat.map({'a': 'x', 'b': 'y', 'c': 'z'}) cat2_pd = cat_pd.map({'a': 'x', 'b': 'y', 'c': 'z'}) # Compare mapped values with pandas for i in range(len(cat2)): if cat2[i] == cat2_pd[i]: f_print_success(f"cat2[{i}] matches pandas: {cat2[i]}") else: f_print_error(f"cat2[{i}] mismatch: pandasCore={cat2[i]}, pandas={cat2_pd[i]}") return False .. _example-categorical-argsort-24: .. dropdown:: argsort (test_categorical.py:1451) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1441 :emphasize-lines: 11 return False def test_argsort(): """Test argsort method (ordered only)""" f_print_header("Test: argsort") try: cat = pandasCore.Categorical(['c', 'a', 'b'], ordered=True) cat_pd = pd.Categorical(['c', 'a', 'b'], ordered=True) indices = cat.argsort() indices_pd = list(cat_pd.argsort()) f_print_info(f"argsort() = {indices}") f_print_info(f"categories = {cat.categories}") # Compare argsort with pandas if indices == indices_pd: f_print_success(f"argsort matches pandas: {indices}") else: f_print_error(f"argsort mismatch: pandasCore={indices}, pandas={indices_pd}") .. _example-categorical-searchsorted-25: .. dropdown:: searchsorted (test_categorical.py:1156) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1146 :emphasize-lines: 11 def test_searchsorted(): """Test searchsorted method""" f_print_header("Test: searchsorted") try: # Must be ordered for searchsorted cat = pandasCore.Categorical(['a', 'b', 'c', 'd'], ordered=True) cat_pd = pd.Categorical(['a', 'b', 'c', 'd'], ordered=True) idx = cat.searchsorted('b') idx_pd = cat_pd.searchsorted('b') # Compare searchsorted result with pandas if idx == idx_pd: f_print_success(f"searchsorted('b') matches pandas: {idx}") else: f_print_error(f"searchsorted mismatch: pandasCore={idx}, pandas={idx_pd}") return False return True .. _example-categorical-sort_values-26: .. dropdown:: sort_values (test_categorical.py:1554) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1544 :emphasize-lines: 11 return False def test_sort_values(): """Test sort_values method (ordered only)""" f_print_header("Test: sort_values (Phase 5)") try: cat = pandasCore.Categorical(['c', 'a', 'b'], ordered=True) cat_pd = pd.Categorical(['c', 'a', 'b'], ordered=True) sorted_cat = cat.sort_values() sorted_cat_pd = cat_pd.sort_values() f_print_info(f"original categories = {cat.categories}") f_print_info(f"sorted values = {sorted_cat.to_list()}") # Compare sort_values with pandas if sorted_cat.to_list() == list(sorted_cat_pd): f_print_success(f"sort_values() matches pandas: {sorted_cat.to_list()}") else: f_print_error(f"sort_values() mismatch: pandasCore={sorted_cat.to_list()}, pandas={list(sorted_cat_pd)}") .. _example-categorical-swapaxes-27: .. dropdown:: swapaxes (test_categorical.py:2135) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 2125 :emphasize-lines: 11 def test_swapaxes(): """Test swapaxes method""" f_print_header("Test: swapaxes (Phase 7)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # swapaxes(0, 0) should work (returns copy) swapped = cat.swapaxes(0, 0) swapped_pd = cat_pd.swapaxes(0, 0) if swapped.size == swapped_pd.size: f_print_success(f"swapaxes(0, 0) size matches pandas: {swapped.size}") else: f_print_error(f"swapaxes(0, 0) size mismatch: pandasCore={swapped.size}, pandas={swapped_pd.size}") return False # Test values match pandas if swapped.to_list() == list(swapped_pd): f_print_success("swapaxes(0, 0) values match pandas") .. _example-categorical-transpose-28: .. dropdown:: transpose (test_categorical.py:2096) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 2086 :emphasize-lines: 11 def test_transpose(): """Test transpose method""" f_print_header("Test: transpose (Phase 7)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # transpose is no-op for 1-D (returns copy) transposed = cat.transpose() transposed_pd = cat_pd.T if transposed.size == transposed_pd.size: f_print_success(f"transpose() size matches pandas: {transposed.size}") else: f_print_error(f"transpose() size mismatch: pandasCore={transposed.size}, pandas={transposed_pd.size}") return False # Test values match pandas if transposed.to_list() == list(transposed_pd): f_print_success("transpose() values match pandas") .. _example-categorical-shift-29: .. dropdown:: shift (test_categorical.py:1180) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1170 :emphasize-lines: 11 return False def test_shift(): """Test shift method""" f_print_header("Test: shift") try: cat = pandasCore.Categorical(['a', 'b', 'c', 'd']) cat_pd = pd.Categorical(['a', 'b', 'c', 'd']) cat2 = cat.shift(1) cat2_pd = cat_pd.shift(1) # Compare shift size with pandas if cat2.size == cat2_pd.size: f_print_success(f"shift size matches pandas: {cat2.size}") else: f_print_error(f"shift size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}") return False # Compare shift codes with pandas .. _example-categorical-to_list-30: .. dropdown:: to_list (test_categorical.py:1600) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1590 :emphasize-lines: 11 def test_to_list(): """Test to_list method""" f_print_header("Test: to_list") try: import numpy as np cat = pandasCore.Categorical(['a', None, 'b', 'c']) cat_pd = pd.Categorical(['a', np.nan, 'b', 'c']) lst = cat.to_list() lst_pd = cat_pd.tolist() # Compare lengths if len(lst) == len(lst_pd): f_print_success(f"to_list() length matches pandas: {len(lst)}") else: f_print_error(f"to_list() length mismatch: pandasCore={len(lst)}, pandas={len(lst_pd)}") return False # Compare non-NA values .. _example-categorical-to_numpy-31: .. dropdown:: to_numpy (test_categorical.py:1751) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1741 :emphasize-lines: 11 def test_to_numpy(): """Test to_numpy method""" f_print_header("Test: to_numpy (Phase 6)") try: import numpy as np cat = pandasCore.Categorical(['a', 'b', 'c', 'a']) cat_pd = pd.Categorical(['a', 'b', 'c', 'a']) arr = cat.to_numpy() arr_pd = cat_pd.codes # pandas to_numpy returns actual values, but we return codes # to_numpy returns codes as numpy array if isinstance(arr, np.ndarray): f_print_success(f"to_numpy returns numpy.ndarray") else: f_print_error(f"to_numpy should return numpy.ndarray, got {type(arr)}") return False # Compare length with pandas codes .. _example-categorical-tolist-32: .. dropdown:: tolist (test_categorical.py:1718) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1708 :emphasize-lines: 11 # Phase 6: Conversion & Output Methods # ============================================================================= def test_tolist(): """Test tolist method (alias for to_list)""" f_print_header("Test: tolist (Phase 6)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) lst = cat.tolist() lst_pd = cat_pd.tolist() # Compare tolist with pandas if lst == lst_pd: f_print_success(f"tolist() matches pandas: {lst}") else: f_print_error(f"tolist() mismatch: pandasCore={lst}, pandas={lst_pd}") return False # Verify tolist is same as to_list .. _example-categorical-astype-33: .. dropdown:: astype (test_categorical.py:1796) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1786 :emphasize-lines: 11 """Test astype method""" f_print_header("Test: astype (Phase 6)") try: import numpy as np cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # Test astype('str') and compare with pandas str_result = cat.astype('str') str_result_pd = list(cat_pd.astype('str')) if str_result == str_result_pd: f_print_success(f"astype('str') matches pandas: {str_result}") else: f_print_error(f"astype('str') mismatch: pandasCore={str_result}, pandas={str_result_pd}") return False # Test astype('object') and compare with pandas obj_result = cat.astype('object') obj_result_pd = list(cat_pd.astype('object')) .. _example-categorical-copy-34: .. dropdown:: copy (test_categorical.py:762) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 752 :emphasize-lines: 11 return False def test_copy(): """Test copy method""" f_print_header("Test: copy") try: cat = pandasCore.Categorical(['a', 'b', 'c', 'a']) cat_pd = pd.Categorical(['a', 'b', 'c', 'a']) cat2 = cat.copy() cat2_pd = cat_pd.copy() # Compare copy size with pandas if cat2.size == cat2_pd.size: f_print_success(f"copy size matches pandas: {cat2.size}") else: f_print_error(f"copy size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}") return False # Compare copy values with pandas .. _example-categorical-view-35: .. dropdown:: view (test_categorical.py:1919) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1909 :emphasize-lines: 11 return False def test_view(): """Test view method""" f_print_header("Test: view (Phase 6)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) v = cat.view() v_pd = cat_pd.view(cat_pd.dtype) # Compare view size with pandas if v.size == v_pd.size: f_print_success(f"view() size matches pandas: {v.size}") else: f_print_error(f"view() size mismatch: pandasCore={v.size}, pandas={v_pd.size}") return False # Check values match .. _example-categorical-duplicated-36: .. dropdown:: duplicated (test_categorical.py:1879) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1869 :emphasize-lines: 11 def test_duplicated(): """Test duplicated method""" f_print_header("Test: duplicated (Phase 6)") try: cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'b']) cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'b']) # Compare duplicated(keep='first') with pandas dup_first = cat.duplicated() dup_first_pd = list(cat_pd.duplicated()) if dup_first == dup_first_pd: f_print_success(f"duplicated(keep='first') matches pandas: {dup_first}") else: f_print_error(f"duplicated(keep='first') mismatch: pandasCore={dup_first}, pandas={dup_first_pd}") return False # Compare duplicated(keep='last') with pandas dup_last = cat.duplicated(keep='last') dup_last_pd = list(cat_pd.duplicated(keep='last')) .. _example-categorical-isin-37: .. dropdown:: isin (test_categorical.py:1118) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1108 :emphasize-lines: 11 return False def test_isin(): """Test isin method""" f_print_header("Test: isin") try: cat = pandasCore.Categorical(['a', 'b', 'c', 'd', 'e']) cat_pd = pd.Categorical(['a', 'b', 'c', 'd', 'e']) result = cat.isin(['a', 'c', 'e']) result_pd = list(cat_pd.isin(['a', 'c', 'e'])) # Compare isin result with pandas if result == result_pd: f_print_success(f"isin matches pandas: {result}") else: f_print_error(f"isin mismatch: pandasCore={result}, pandas={result_pd}") return False # Test with NA values .. _example-categorical-unique-38: .. dropdown:: unique (test_categorical.py:843) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 833 :emphasize-lines: 11 return False def test_unique(): """Test unique method""" f_print_header("Test: unique") try: cat = pandasCore.Categorical(['a', 'b', 'a', 'c', 'b', 'a']) cat_pd = pd.Categorical(['a', 'b', 'a', 'c', 'b', 'a']) uniq = cat.unique() uniq_pd = cat_pd.unique() # Compare unique count with pandas if uniq.size == uniq_pd.size: f_print_success(f"unique count matches pandas: {uniq.size}") else: f_print_error(f"unique count mismatch: pandasCore={uniq.size}, pandas={uniq_pd.size}") return False # Compare unique values with pandas (order may vary, use set) .. _example-categorical-add_categories-39: .. dropdown:: add_categories (test_cat_accessor.py:33) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 23 :emphasize-lines: 11 assert len(codes) == 5, f"codes length: {len(codes)}" # ordered assert s.cat.ordered == False, f"ordered: {s.cat.ordered}" def test_cat_add_categories(): """Test add_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.add_categories(['d', 'e']) assert 'd' in result, f"add_categories result: {result}" assert 'e' in result def test_cat_remove_categories(): """Test remove_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.remove_categories(['c']) assert 'c' not in result, f"remove_categories result: {result}" .. _example-categorical-as_ordered-40: .. dropdown:: as_ordered (test_cat_accessor.py:112) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 102 :emphasize-lines: 11 # With rename=True result3 = s.cat.set_categories(['1', '2', '3'], rename=True) assert result3 == ['1', '2', '3'], f"set_categories rename: {result3}" def test_cat_as_ordered(): """Test as_ordered method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.as_ordered() assert result.ordered == True, f"as_ordered: {result.ordered}" def test_cat_as_unordered(): """Test as_unordered method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) ordered_cat = s.cat.as_ordered() result = ordered_cat.as_unordered() assert result.ordered == False, f"as_unordered: {result.ordered}" .. _example-categorical-as_unordered-41: .. dropdown:: as_unordered (test_categorical_accessor_comp.py:252) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 242 :emphasize-lines: 11 ctx.assert_false(pc_series.cat.ordered, "pc initially unordered") pc_result = pc_series.cat.as_ordered() # as_ordered returns a CategoricalAccessor with ordered=True pc_ordered = pc_result.ordered ctx.assert_equal(pd_ordered, pc_ordered, "as_ordered()") ctx.assert_true(pc_ordered, "as_ordered result is True") def test_cat_as_unordered(): """Test .cat.as_unordered() method""" f_print_header("Test: .cat.as_unordered()") # pandas pd_cat = pd.Categorical(['a', 'b', 'c'], ordered=True) pd_series = pd.Series(pd_cat) ctx.assert_true(pd_series.cat.ordered, "pd initially ordered") pd_result = pd_series.cat.as_unordered() pd_ordered = pd_result.cat.ordered # pandasCore - first make it ordered, then unordered .. _example-categorical-remove_categories-42: .. dropdown:: remove_categories (test_cat_accessor.py:42) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 32 :emphasize-lines: 11 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.add_categories(['d', 'e']) assert 'd' in result, f"add_categories result: {result}" assert 'e' in result def test_cat_remove_categories(): """Test remove_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.remove_categories(['c']) assert 'c' not in result, f"remove_categories result: {result}" assert 'a' in result assert 'b' in result def test_cat_remove_unused_categories(): """Test remove_unused_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'a', 'b']) # Only 'a' and 'b' are used result = s.cat.remove_unused_categories() .. _example-categorical-remove_unused_categories-43: .. dropdown:: remove_unused_categories (test_cat_accessor.py:52) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 42 :emphasize-lines: 11 result = s.cat.remove_categories(['c']) assert 'c' not in result, f"remove_categories result: {result}" assert 'a' in result assert 'b' in result def test_cat_remove_unused_categories(): """Test remove_unused_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'a', 'b']) # Only 'a' and 'b' are used result = s.cat.remove_unused_categories() assert len(result) == 2, f"remove_unused_categories: {result}" def test_cat_rename_categories_list(): """Test rename_categories with list""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.rename_categories(['x', 'y', 'z']) assert result == ['x', 'y', 'z'], f"rename_categories (list): {result}" .. _example-categorical-rename_categories-44: .. dropdown:: rename_categories (test_cat_accessor.py:60) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 50 :emphasize-lines: 11 tests_run += 1 s = pandasCore.StringSeries(['a', 'a', 'b']) # Only 'a' and 'b' are used result = s.cat.remove_unused_categories() assert len(result) == 2, f"remove_unused_categories: {result}" def test_cat_rename_categories_list(): """Test rename_categories with list""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.rename_categories(['x', 'y', 'z']) assert result == ['x', 'y', 'z'], f"rename_categories (list): {result}" def test_cat_rename_categories_dict(): """Test rename_categories with dict""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.rename_categories({'a': 'alpha', 'b': 'beta'}) assert 'alpha' in result, f"rename_categories (dict): {result}" assert 'beta' in result .. _example-categorical-reorder_categories-45: .. dropdown:: reorder_categories (test_cat_accessor.py:78) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 68 :emphasize-lines: 11 result = s.cat.rename_categories({'a': 'alpha', 'b': 'beta'}) assert 'alpha' in result, f"rename_categories (dict): {result}" assert 'beta' in result assert 'c' in result # Unchanged def test_cat_reorder_categories(): """Test reorder_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.reorder_categories(['c', 'b', 'a']) assert result == ['c', 'b', 'a'], f"reorder_categories: {result}" def test_cat_reorder_categories_ordered(): """Test reorder_categories with ordered parameter""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) result = s.cat.reorder_categories(['c', 'b', 'a'], ordered=True) assert result == ['c', 'b', 'a'], f"reorder_categories ordered: {result}" .. _example-categorical-set_categories-46: .. dropdown:: set_categories (test_cat_accessor.py:96) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 86 :emphasize-lines: 11 result = s.cat.reorder_categories(['c', 'b', 'a'], ordered=True) assert result == ['c', 'b', 'a'], f"reorder_categories ordered: {result}" def test_cat_set_categories(): """Test set_categories method""" global tests_run tests_run += 1 s = pandasCore.StringSeries(['a', 'b', 'c']) # Default: ordered=False, rename=False result = s.cat.set_categories(['x', 'y', 'z']) assert result == ['x', 'y', 'z'], f"set_categories default: {result}" # With ordered=True result2 = s.cat.set_categories(['p', 'q', 'r'], ordered=True) assert result2 == ['p', 'q', 'r'], f"set_categories ordered: {result2}" # With rename=True result3 = s.cat.set_categories(['1', '2', '3'], rename=True) assert result3 == ['1', '2', '3'], f"set_categories rename: {result3}" .. _example-categorical-argmax-47: .. dropdown:: argmax (test_categorical.py:1518) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1508 :emphasize-lines: 11 return False def test_argmax(): """Test argmax method (ordered only)""" f_print_header("Test: argmax (Phase 5)") try: cat = pandasCore.Categorical(['b', 'a', 'c', 'a'], ordered=True) cat_pd = pd.Categorical(['b', 'a', 'c', 'a'], ordered=True) idx = cat.argmax() idx_pd = cat_pd.argmax() f_print_info(f"categories = {cat.categories}") f_print_info(f"argmax() = {idx}") # Compare argmax with pandas if idx == idx_pd: f_print_success(f"argmax() matches pandas: {idx}") else: f_print_error(f"argmax() mismatch: pandasCore={idx}, pandas={idx_pd}") .. _example-categorical-argmin-48: .. dropdown:: argmin (test_categorical.py:1482) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1472 :emphasize-lines: 11 # Phase 5: Statistics & Ordering Methods # ============================================================================= def test_argmin(): """Test argmin method (ordered only)""" f_print_header("Test: argmin (Phase 5)") try: cat = pandasCore.Categorical(['b', 'a', 'c', 'a'], ordered=True) cat_pd = pd.Categorical(['b', 'a', 'c', 'a'], ordered=True) idx = cat.argmin() idx_pd = cat_pd.argmin() f_print_info(f"categories = {cat.categories}") f_print_info(f"argmin() = {idx}") # Compare argmin with pandas if idx == idx_pd: f_print_success(f"argmin() matches pandas: {idx}") else: f_print_error(f"argmin() mismatch: pandasCore={idx}, pandas={idx_pd}") .. _example-categorical-delete-49: .. dropdown:: delete (test_categorical.py:1044) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1034 :emphasize-lines: 11 return False def test_delete(): """Test delete method""" f_print_header("Test: delete") try: cat = pandasCore.Categorical(['a', 'b', 'c', 'd']) cat_pd = pd.Categorical(['a', 'b', 'c', 'd']) cat2 = cat.delete(1) # Delete 'b' cat2_pd = cat_pd.delete(1) # Compare delete size with pandas if cat2.size == cat2_pd.size: f_print_success(f"delete size matches pandas: {cat2.size}") else: f_print_error(f"delete size mismatch: pandasCore={cat2.size}, pandas={cat2_pd.size}") return False # Compare delete values with pandas .. _example-categorical-factorize-50: .. dropdown:: factorize (test_categorical.py:876) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 866 :emphasize-lines: 11 return False def test_factorize(): """Test factorize method""" f_print_header("Test: factorize") try: cat = pandasCore.Categorical(['a', 'b', 'a', 'c']) cat_pd = pd.Categorical(['a', 'b', 'a', 'c']) codes, uniques = cat.factorize() codes_pd, uniques_pd = cat_pd.factorize() # Compare codes length with pandas if len(codes) == len(codes_pd): f_print_success(f"codes length matches pandas: {len(codes)}") else: f_print_error(f"codes length mismatch: pandasCore={len(codes)}, pandas={len(codes_pd)}") return False # Compare uniques count with pandas .. _example-categorical-memory_usage-51: .. dropdown:: memory_usage (test_categorical.py:1846) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1836 :emphasize-lines: 11 def test_memory_usage(): """Test memory_usage method""" f_print_header("Test: memory_usage (Phase 6)") try: cat = pandasCore.Categorical(['a', 'b', 'c', 'a', 'b']) cat_pd = pd.Categorical(['a', 'b', 'c', 'a', 'b']) # Basic memory_usage - both should be positive mem = cat.memory_usage() mem_pd = cat_pd.memory_usage() if isinstance(mem, int) and mem > 0 and isinstance(mem_pd, int) and mem_pd > 0: f_print_success(f"memory_usage() both positive: pandasCore={mem}, pandas={mem_pd}") else: f_print_error(f"memory_usage() should be positive int: pandasCore={mem}, pandas={mem_pd}") return False # memory_usage with deep=True mem_deep = cat.memory_usage(deep=True) mem_deep_pd = cat_pd.memory_usage(deep=True) .. _example-categorical-ravel-52: .. dropdown:: ravel (test_categorical.py:2058) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 2048 :emphasize-lines: 11 def test_ravel(): """Test ravel method""" f_print_header("Test: ravel (Phase 7)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # ravel returns copy (already 1-D) raveled = cat.ravel() raveled_pd = cat_pd.ravel() if raveled.size == raveled_pd.size: f_print_success(f"ravel() size matches pandas: {raveled.size}") else: f_print_error(f"ravel() size mismatch: pandasCore={raveled.size}, pandas={raveled_pd.size}") return False # Test values match pandas if raveled.to_list() == list(raveled_pd): f_print_success("ravel() values match pandas") .. _example-categorical-repeat-53: .. dropdown:: repeat (test_categorical.py:1963) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 1953 :emphasize-lines: 11 def test_repeat(): """Test repeat method""" f_print_header("Test: repeat (Phase 7)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # Compare repeat(2) with pandas repeated = cat.repeat(2) repeated_pd = cat_pd.repeat(2) if repeated.to_list() == list(repeated_pd): f_print_success(f"repeat(2) matches pandas: {repeated.to_list()}") else: f_print_error(f"repeat(2) mismatch: pandasCore={repeated.to_list()}, pandas={list(repeated_pd)}") return False # Compare size with pandas if repeated.size == repeated_pd.size: f_print_success(f"repeat(2) size matches pandas: {repeated.size}") .. _example-categorical-reshape-54: .. dropdown:: reshape (test_categorical.py:2020) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 2010 :emphasize-lines: 11 def test_reshape(): """Test reshape method""" f_print_header("Test: reshape (Phase 7)") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # Compare reshape(-1) with pandas (pandas uses codes reshape) reshaped = cat.reshape(-1) if reshaped.size == cat_pd.size: f_print_success(f"reshape(-1) size matches original: {reshaped.size}") else: f_print_error(f"reshape(-1) size wrong: {reshaped.size}, expected {cat_pd.size}") return False # Test values preserved if reshaped.to_list() == list(cat_pd): f_print_success("reshape(-1) values match pandas") else: .. _example-categorical-set_ordered-55: .. dropdown:: set_ordered (test_categorical.py:638) :class-title: example-dropdown .. code-block:: python :linenos: :lineno-start: 628 :emphasize-lines: 11 def test_set_ordered(): """Test set_ordered method""" f_print_header("Test: set_ordered") try: cat = pandasCore.Categorical(['a', 'b', 'c']) cat_pd = pd.Categorical(['a', 'b', 'c']) # Set to ordered cat_ord = cat.set_ordered(True) cat_ord_pd = cat_pd.set_ordered(True) if cat_ord.ordered == cat_ord_pd.ordered: f_print_success(f"set_ordered(True) matches pandas: {cat_ord.ordered}") else: f_print_error(f"set_ordered(True) mismatch: pandasCore={cat_ord.ordered}, pandas={cat_ord_pd.ordered}") return False # Set back to unordered cat_unord = cat_ord.set_ordered(False) cat_unord_pd = cat_ord_pd.set_ordered(False)