diff --git a/pandas/core/generic.py b/pandas/core/generic.py index b747f0a2ceacb..0deef1b7cd3b7 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1286,23 +1286,25 @@ def _check_setitem_copy(self, stacklevel=4, t='setting', force=False): elif t == 'referant': t = ("\n" "A value is trying to be set on a copy of a slice from a " - "DataFrame\n\n" + "{name}\n\n" "See the the caveats in the documentation: " "http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy") else: t = ("\n" "A value is trying to be set on a copy of a slice from a " - "DataFrame.\n" + "{name}.\n" "Try using .loc[row_indexer,col_indexer] = value instead\n\n" "See the the caveats in the documentation: " "http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy") + t = t.format(name=type(self).__name__) + if value == 'raise': raise SettingWithCopyError(t) elif value == 'warn': warnings.warn(t, SettingWithCopyWarning, stacklevel=stacklevel) - + def __delitem__(self, key): """ Delete item diff --git a/pandas/core/series.py b/pandas/core/series.py index 8ef9adb1d24a4..23b75bd1a95f3 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -562,7 +562,10 @@ def _get_with(self, key): # other: fancy integer or otherwise if isinstance(key, slice): indexer = self.index._convert_slice_indexer(key, kind='getitem') - return self._get_values(indexer) + values = self._get_values(indexer) + is_copy = values._is_view + values._set_is_copy(self, copy=is_copy) + return values elif isinstance(key, ABCDataFrame): raise TypeError('Indexing a Series with DataFrame is not supported, '\ 'use the appropriate DataFrame column') @@ -684,6 +687,7 @@ def setitem(key, value): # do the setitem cacher_needs_updating = self._check_is_chained_assignment_possible() setitem(key, value) + self._check_setitem_copy() if cacher_needs_updating: self._maybe_update_cacher() diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 925cfa875196c..2fbc072fe8f68 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -569,7 +569,6 @@ def setUp(self): self.ts = _ts.copy() self.ts.name = 'ts' - self.series = tm.makeStringSeries() self.series.name = 'series' @@ -1360,11 +1359,12 @@ def test_slice(self): self.assertTrue(tm.equalContents(numSliceEnd, np.array(self.series)[-10:])) - - # test return view - sl = self.series[10:20] - sl[:] = 0 - self.assertTrue((self.series[10:20] == 0).all()) + # After fix for #10193, this is needed + with pd.option_context('chained_assignment', 'warn'): + # test return view + sl = self.series[10:20] + sl[:] = 0 + self.assertTrue((self.series[10:20] == 0).all()) def test_slice_can_reorder_not_uniquely_indexed(self): s = Series(1, index=['a', 'a', 'b', 'b', 'c']) @@ -1439,6 +1439,36 @@ def test_setitem(self): expected = self.series.append(Series([1],index=['foobar'])) assert_series_equal(s,expected) + # Test for issue #10193 + key = datetime(2012, 1, 1) + series = pd.Series() + series[key] = 47 + expected = pd.Series(47, [key]) + assert_series_equal(series, expected) + + test_values = [ + (pd.date_range('2011-01-01', '2011-01-01'), datetime(2012, 1, 1)), + (pd.Int64Index([1, 2, 3]), 5) + ] + for idx, key in test_values: + + series = pd.Series(0, idx) + series2 = series[:0] + + def f(): + series2[key] = 47 + + expected = pd.Series(47, [key]) + + with pd.option_context('chained_assignment', 'raise'): + self.assertRaises(com.SettingWithCopyError, f) + + with pd.option_context('chained_assignment', 'warn'): + f() + assert_series_equal(series2, expected) + # also check that original series remains unchanged. + assert_series_equal(series, pd.Series(0, idx)) + def test_setitem_dtypes(self): # change dtypes @@ -4271,15 +4301,14 @@ def test_underlying_data_conversion(self): # GH 3970 # these are chained assignments as well - pd.set_option('chained_assignment',None) - df = DataFrame({ "aa":range(5), "bb":[2.2]*5}) - df["cc"] = 0.0 - ck = [True]*len(df) - df["bb"].iloc[0] = .13 - df_tmp = df.iloc[ck] - df["bb"].iloc[0] = .15 - self.assertEqual(df['bb'].iloc[0], 0.15) - pd.set_option('chained_assignment','raise') + with pd.option_context('chained_assignment',None): + df = DataFrame({ "aa":range(5), "bb":[2.2]*5}) + df["cc"] = 0.0 + ck = [True]*len(df) + df["bb"].iloc[0] = .13 + df_tmp = df.iloc[ck] + df["bb"].iloc[0] = .15 + self.assertEqual(df['bb'].iloc[0], 0.15) # GH 3217 df = DataFrame(dict(a = [1,3], b = [np.nan, 2])) @@ -4816,9 +4845,11 @@ def test_rank(self): tm._skip_if_no_scipy() from scipy.stats import rankdata - self.ts[::2] = np.nan - self.ts[:10][::3] = 4. - + # After fix for #10193, this is needed + with pd.option_context('chained_assignment',None): + self.ts[::2] = np.nan + self.ts[:10][::3] = 4. + ranks = self.ts.rank() oranks = self.ts.astype('O').rank() diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index bd0869b9525b7..f360503abb1a8 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -1521,7 +1521,7 @@ def insert(self, loc, item): if zone != izone: raise ValueError('Passed item and index have different timezone') # check freq can be preserved on edge cases - if self.freq is not None: + if self.size and self.freq is not None: if (loc == 0 or loc == -len(self)) and item + self.freq == self[0]: freq = self.freq elif (loc == len(self)) and item - self.freq == self[-1]: diff --git a/pandas/tseries/tests/test_period.py b/pandas/tseries/tests/test_period.py index 0218af63ca7d6..e05ce1b9baaf4 100644 --- a/pandas/tseries/tests/test_period.py +++ b/pandas/tseries/tests/test_period.py @@ -1669,7 +1669,10 @@ def test_index_duplicate_periods(self): result = ts[2007] expected = ts[1:3] assert_series_equal(result, expected) - result[:] = 1 + # After fix for #10193, this is necessary + with pd.option_context('chained_assignment',None): + result[:] = 1 + self.assertTrue((ts[1:3] == 1).all()) # not monotonic