|
| 1 | +import numpy as np |
| 2 | +import pytest |
| 3 | + |
| 4 | +import pandas as pd |
| 5 | +import pandas._testing as tm |
| 6 | +from pandas.arrays import BooleanArray |
| 7 | +from pandas.tests.extension.base import BaseOpsUtil |
| 8 | + |
| 9 | + |
| 10 | +@pytest.fixture |
| 11 | +def data(): |
| 12 | + return pd.array( |
| 13 | + [True, False] * 4 + [np.nan] + [True, False] * 44 + [np.nan] + [True, False], |
| 14 | + dtype="boolean", |
| 15 | + ) |
| 16 | + |
| 17 | + |
| 18 | +class TestComparisonOps(BaseOpsUtil): |
| 19 | + def _compare_other(self, data, op_name, other): |
| 20 | + op = self.get_op_from_name(op_name) |
| 21 | + |
| 22 | + # array |
| 23 | + result = pd.Series(op(data, other)) |
| 24 | + expected = pd.Series(op(data._data, other), dtype="boolean") |
| 25 | + # propagate NAs |
| 26 | + expected[data._mask] = pd.NA |
| 27 | + |
| 28 | + tm.assert_series_equal(result, expected) |
| 29 | + |
| 30 | + # series |
| 31 | + s = pd.Series(data) |
| 32 | + result = op(s, other) |
| 33 | + |
| 34 | + expected = pd.Series(data._data) |
| 35 | + expected = op(expected, other) |
| 36 | + expected = expected.astype("boolean") |
| 37 | + # propagate NAs |
| 38 | + expected[data._mask] = pd.NA |
| 39 | + |
| 40 | + tm.assert_series_equal(result, expected) |
| 41 | + |
| 42 | + def test_compare_scalar(self, data, all_compare_operators): |
| 43 | + op_name = all_compare_operators |
| 44 | + self._compare_other(data, op_name, True) |
| 45 | + |
| 46 | + def test_compare_array(self, data, all_compare_operators): |
| 47 | + op_name = all_compare_operators |
| 48 | + other = pd.array([True] * len(data), dtype="boolean") |
| 49 | + self._compare_other(data, op_name, other) |
| 50 | + other = np.array([True] * len(data)) |
| 51 | + self._compare_other(data, op_name, other) |
| 52 | + other = pd.Series([True] * len(data)) |
| 53 | + self._compare_other(data, op_name, other) |
| 54 | + |
| 55 | + @pytest.mark.parametrize("other", [True, False, pd.NA]) |
| 56 | + def test_scalar(self, other, all_compare_operators): |
| 57 | + op = self.get_op_from_name(all_compare_operators) |
| 58 | + a = pd.array([True, False, None], dtype="boolean") |
| 59 | + |
| 60 | + result = op(a, other) |
| 61 | + |
| 62 | + if other is pd.NA: |
| 63 | + expected = pd.array([None, None, None], dtype="boolean") |
| 64 | + else: |
| 65 | + values = op(a._data, other) |
| 66 | + expected = BooleanArray(values, a._mask, copy=True) |
| 67 | + tm.assert_extension_array_equal(result, expected) |
| 68 | + |
| 69 | + # ensure we haven't mutated anything inplace |
| 70 | + result[0] = None |
| 71 | + tm.assert_extension_array_equal( |
| 72 | + a, pd.array([True, False, None], dtype="boolean") |
| 73 | + ) |
| 74 | + |
| 75 | + def test_array(self, all_compare_operators): |
| 76 | + op = self.get_op_from_name(all_compare_operators) |
| 77 | + a = pd.array([True] * 3 + [False] * 3 + [None] * 3, dtype="boolean") |
| 78 | + b = pd.array([True, False, None] * 3, dtype="boolean") |
| 79 | + |
| 80 | + result = op(a, b) |
| 81 | + |
| 82 | + values = op(a._data, b._data) |
| 83 | + mask = a._mask | b._mask |
| 84 | + expected = BooleanArray(values, mask) |
| 85 | + tm.assert_extension_array_equal(result, expected) |
| 86 | + |
| 87 | + # ensure we haven't mutated anything inplace |
| 88 | + result[0] = None |
| 89 | + tm.assert_extension_array_equal( |
| 90 | + a, pd.array([True] * 3 + [False] * 3 + [None] * 3, dtype="boolean") |
| 91 | + ) |
| 92 | + tm.assert_extension_array_equal( |
| 93 | + b, pd.array([True, False, None] * 3, dtype="boolean") |
| 94 | + ) |
0 commit comments