From 323edb6066721e5671d77972db233906d7dbcf3d Mon Sep 17 00:00:00 2001 From: Brock Date: Fri, 29 Jan 2021 19:24:02 -0800 Subject: [PATCH] TST/REF: SetitemCastingEquivalents --- pandas/tests/series/indexing/test_setitem.py | 150 +++++++++++-------- 1 file changed, 89 insertions(+), 61 deletions(-) diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index 36cd6b0327ccd..9ace404930876 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -282,56 +282,9 @@ def test_setitem_dt64_into_int_series(self, dtype): tm.assert_series_equal(ser, expected) -@pytest.mark.parametrize( - "obj,expected,key", - [ - pytest.param( - # these induce dtype changes - Series([2, 3, 4, 5, 6, 7, 8, 9, 10]), - Series([np.nan, 3, np.nan, 5, np.nan, 7, np.nan, 9, np.nan]), - slice(None, None, 2), - id="int_series_slice_key_step", - ), - pytest.param( - Series([True, True, False, False]), - Series([np.nan, True, np.nan, False], dtype=object), - slice(None, None, 2), - id="bool_series_slice_key_step", - ), - pytest.param( - # these induce dtype changes - Series(np.arange(10)), - Series([np.nan, np.nan, np.nan, np.nan, np.nan, 5, 6, 7, 8, 9]), - slice(None, 5), - id="int_series_slice_key", - ), - pytest.param( - # changes dtype GH#4463 - Series([1, 2, 3]), - Series([np.nan, 2, 3]), - 0, - id="int_series_int_key", - ), - pytest.param( - # changes dtype GH#4463 - Series([False]), - Series([np.nan], dtype=object), - # TODO: maybe go to float64 since we are changing the _whole_ Series? - 0, - id="bool_series_int_key_change_all", - ), - pytest.param( - # changes dtype GH#4463 - Series([False, True]), - Series([np.nan, True], dtype=object), - 0, - id="bool_series_int_key", - ), - ], -) -class TestSetitemCastingEquivalents: +class SetitemCastingEquivalents: """ - Check each of several methods that _should_ be equivalent to `obj[key] = np.nan` + Check each of several methods that _should_ be equivalent to `obj[key] = val` We assume that - obj.index is the default Index(range(len(obj))) @@ -346,26 +299,44 @@ def val(self, request): """ return request.param + def check_indexer(self, obj, key, expected, val, indexer): + obj = obj.copy() + indexer(obj)[key] = val + tm.assert_series_equal(obj, expected) + def test_int_key(self, obj, key, expected, val, indexer_sli): if not isinstance(key, int): return - obj = obj.copy() - indexer_sli(obj)[key] = val - tm.assert_series_equal(obj, expected) + self.check_indexer(obj, key, expected, val, indexer_sli) - def test_slice_key(self, obj, key, expected, val, indexer_si): - # Note: no .loc because that handles slice edges differently - obj = obj.copy() - indexer_si(obj)[key] = val - tm.assert_series_equal(obj, expected) + rng = range(key, key + 1) + self.check_indexer(obj, rng, expected, val, indexer_sli) + + if indexer_sli is not tm.loc: + # Note: no .loc because that handles slice edges differently + slc = slice(key, key + 1) + self.check_indexer(obj, slc, expected, val, indexer_sli) + + ilkey = [key] + self.check_indexer(obj, ilkey, expected, val, indexer_sli) + + indkey = np.array(ilkey) + self.check_indexer(obj, indkey, expected, val, indexer_sli) + + def test_slice_key(self, obj, key, expected, val, indexer_sli): + if not isinstance(key, slice): + return + + if indexer_sli is not tm.loc: + # Note: no .loc because that handles slice edges differently + self.check_indexer(obj, key, expected, val, indexer_sli) - def test_intlist_key(self, obj, key, expected, val, indexer_sli): ilkey = list(range(len(obj)))[key] + self.check_indexer(obj, ilkey, expected, val, indexer_sli) - obj = obj.copy() - indexer_sli(obj)[ilkey] = val - tm.assert_series_equal(obj, expected) + indkey = np.array(ilkey) + self.check_indexer(obj, indkey, expected, val, indexer_sli) def test_mask_key(self, obj, key, expected, val, indexer_sli): # setitem with boolean mask @@ -412,6 +383,63 @@ def test_index_putmask(self, obj, key, expected, val): tm.assert_index_equal(res, Index(expected)) +@pytest.mark.parametrize( + "obj,expected,key", + [ + pytest.param( + # these induce dtype changes + Series([2, 3, 4, 5, 6, 7, 8, 9, 10]), + Series([np.nan, 3, np.nan, 5, np.nan, 7, np.nan, 9, np.nan]), + slice(None, None, 2), + id="int_series_slice_key_step", + ), + pytest.param( + Series([True, True, False, False]), + Series([np.nan, True, np.nan, False], dtype=object), + slice(None, None, 2), + id="bool_series_slice_key_step", + ), + pytest.param( + # these induce dtype changes + Series(np.arange(10)), + Series([np.nan, np.nan, np.nan, np.nan, np.nan, 5, 6, 7, 8, 9]), + slice(None, 5), + id="int_series_slice_key", + ), + pytest.param( + # changes dtype GH#4463 + Series([1, 2, 3]), + Series([np.nan, 2, 3]), + 0, + id="int_series_int_key", + ), + pytest.param( + # changes dtype GH#4463 + Series([False]), + Series([np.nan], dtype=object), + # TODO: maybe go to float64 since we are changing the _whole_ Series? + 0, + id="bool_series_int_key_change_all", + ), + pytest.param( + # changes dtype GH#4463 + Series([False, True]), + Series([np.nan, True], dtype=object), + 0, + id="bool_series_int_key", + ), + ], +) +class TestSetitemCastingEquivalents(SetitemCastingEquivalents): + @pytest.fixture(params=[np.nan, np.float64("NaN")]) + def val(self, request): + """ + One python float NaN, one np.float64. Only np.float64 has a `dtype` + attribute. + """ + return request.param + + class TestSetitemWithExpansion: def test_setitem_empty_series(self): # GH#10193