|
9 | 9 | from pandas._libs.tslibs import conversion, timezones
|
10 | 10 |
|
11 | 11 | import pandas as pd
|
12 |
| -from pandas import Series, Timestamp, date_range, period_range |
| 12 | +from pandas import Index, Series, Timestamp, date_range, period_range |
13 | 13 | import pandas._testing as tm
|
| 14 | +from pandas.core.indexing import IndexingError |
| 15 | + |
| 16 | +from pandas.tseries.offsets import BDay |
14 | 17 |
|
15 | 18 |
|
16 | 19 | class TestSeriesGetitemScalars:
|
@@ -124,6 +127,107 @@ def test_getitem_intlist_multiindex_numeric_level(self, dtype, box):
|
124 | 127 | ser[key]
|
125 | 128 |
|
126 | 129 |
|
| 130 | +class TestGetitemBooleanMask: |
| 131 | + def test_getitem_boolean(self, string_series): |
| 132 | + ser = string_series |
| 133 | + mask = ser > ser.median() |
| 134 | + |
| 135 | + # passing list is OK |
| 136 | + result = ser[list(mask)] |
| 137 | + expected = ser[mask] |
| 138 | + tm.assert_series_equal(result, expected) |
| 139 | + tm.assert_index_equal(result.index, ser.index[mask]) |
| 140 | + |
| 141 | + def test_getitem_boolean_empty(self): |
| 142 | + ser = Series([], dtype=np.int64) |
| 143 | + ser.index.name = "index_name" |
| 144 | + ser = ser[ser.isna()] |
| 145 | + assert ser.index.name == "index_name" |
| 146 | + assert ser.dtype == np.int64 |
| 147 | + |
| 148 | + # GH#5877 |
| 149 | + # indexing with empty series |
| 150 | + ser = Series(["A", "B"]) |
| 151 | + expected = Series(dtype=object, index=Index([], dtype="int64")) |
| 152 | + result = ser[Series([], dtype=object)] |
| 153 | + tm.assert_series_equal(result, expected) |
| 154 | + |
| 155 | + # invalid because of the boolean indexer |
| 156 | + # that's empty or not-aligned |
| 157 | + msg = ( |
| 158 | + r"Unalignable boolean Series provided as indexer \(index of " |
| 159 | + r"the boolean Series and of the indexed object do not match" |
| 160 | + ) |
| 161 | + with pytest.raises(IndexingError, match=msg): |
| 162 | + ser[Series([], dtype=bool)] |
| 163 | + |
| 164 | + with pytest.raises(IndexingError, match=msg): |
| 165 | + ser[Series([True], dtype=bool)] |
| 166 | + |
| 167 | + def test_getitem_boolean_object(self, string_series): |
| 168 | + # using column from DataFrame |
| 169 | + |
| 170 | + ser = string_series |
| 171 | + mask = ser > ser.median() |
| 172 | + omask = mask.astype(object) |
| 173 | + |
| 174 | + # getitem |
| 175 | + result = ser[omask] |
| 176 | + expected = ser[mask] |
| 177 | + tm.assert_series_equal(result, expected) |
| 178 | + |
| 179 | + # setitem |
| 180 | + s2 = ser.copy() |
| 181 | + cop = ser.copy() |
| 182 | + cop[omask] = 5 |
| 183 | + s2[mask] = 5 |
| 184 | + tm.assert_series_equal(cop, s2) |
| 185 | + |
| 186 | + # nans raise exception |
| 187 | + omask[5:10] = np.nan |
| 188 | + msg = "Cannot mask with non-boolean array containing NA / NaN values" |
| 189 | + with pytest.raises(ValueError, match=msg): |
| 190 | + ser[omask] |
| 191 | + with pytest.raises(ValueError, match=msg): |
| 192 | + ser[omask] = 5 |
| 193 | + |
| 194 | + def test_getitem_boolean_dt64_copies(self): |
| 195 | + # GH#36210 |
| 196 | + dti = date_range("2016-01-01", periods=4, tz="US/Pacific") |
| 197 | + key = np.array([True, True, False, False]) |
| 198 | + |
| 199 | + ser = Series(dti._data) |
| 200 | + |
| 201 | + res = ser[key] |
| 202 | + assert res._values._data.base is None |
| 203 | + |
| 204 | + # compare with numeric case for reference |
| 205 | + ser2 = Series(range(4)) |
| 206 | + res2 = ser2[key] |
| 207 | + assert res2._values.base is None |
| 208 | + |
| 209 | + def test_getitem_boolean_corner(self, datetime_series): |
| 210 | + ts = datetime_series |
| 211 | + mask_shifted = ts.shift(1, freq=BDay()) > ts.median() |
| 212 | + |
| 213 | + msg = ( |
| 214 | + r"Unalignable boolean Series provided as indexer \(index of " |
| 215 | + r"the boolean Series and of the indexed object do not match" |
| 216 | + ) |
| 217 | + with pytest.raises(IndexingError, match=msg): |
| 218 | + ts[mask_shifted] |
| 219 | + |
| 220 | + with pytest.raises(IndexingError, match=msg): |
| 221 | + ts.loc[mask_shifted] |
| 222 | + |
| 223 | + def test_getitem_boolean_different_order(self, string_series): |
| 224 | + ordered = string_series.sort_values() |
| 225 | + |
| 226 | + sel = string_series[ordered > 0] |
| 227 | + exp = string_series[string_series > 0] |
| 228 | + tm.assert_series_equal(sel, exp) |
| 229 | + |
| 230 | + |
127 | 231 | def test_getitem_generator(string_series):
|
128 | 232 | gen = (x > 0 for x in string_series)
|
129 | 233 | result = string_series[gen]
|
|
0 commit comments