diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 620823b9703ab..790895f5f4f81 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -464,7 +464,7 @@ def __new__( cls, data=None, dtype=None, - copy: bool = False, + copy: bool | None = None, name=None, tupleize_cols: bool = True, ) -> Index: @@ -477,6 +477,12 @@ def __new__( data_dtype = getattr(data, "dtype", None) + if copy is None: + if isinstance(data, Index): + copy = False + else: + copy = True + # range if isinstance(data, (range, RangeIndex)): result = RangeIndex(start=data, copy=copy, name=name) @@ -6714,7 +6720,7 @@ def infer_objects(self, copy: bool = True) -> Index: ) if copy and res_values is values: return self.copy() - return Index(res_values, name=self.name) + return Index(res_values, name=self.name, copy=False) # -------------------------------------------------------------------- # Generated Arithmetic, Comparison, and Unary Methods @@ -7051,7 +7057,7 @@ def ensure_index_from_sequences(sequences, names=None) -> Index: return MultiIndex.from_arrays(sequences, names=names) -def ensure_index(index_like: Axes, copy: bool = False) -> Index: +def ensure_index(index_like: Axes, copy: bool | None = None) -> Index: """ Ensure that we have an index from some index-like object. @@ -7059,7 +7065,8 @@ def ensure_index(index_like: Axes, copy: bool = False) -> Index: ---------- index_like : sequence An Index or other sequence - copy : bool, default False + copy : bool, optional + By default copy if the passed object is not yet an Index object. Returns ------- @@ -7083,10 +7090,13 @@ def ensure_index(index_like: Axes, copy: bool = False) -> Index: ) """ if isinstance(index_like, Index): - if copy: + if copy is True: index_like = index_like.copy() return index_like + if copy is None: + copy = True + if isinstance(index_like, ABCSeries): name = index_like.name return Index(index_like, name=name, copy=copy) diff --git a/pandas/tests/copy_view/test_indexes.py b/pandas/tests/copy_view/test_indexes.py new file mode 100644 index 0000000000000..c805b3f69f145 --- /dev/null +++ b/pandas/tests/copy_view/test_indexes.py @@ -0,0 +1,44 @@ +from pandas import ( + DataFrame, + Index, + Series, +) +import pandas._testing as tm + + +def test_index_constructor(): + ser = Series([1, 2, 3]) + idx = Index(ser) + # assert not np.shares_memory(idx.values, get_array(ser)) + ser.iloc[0] = 0 + tm.assert_index_equal(idx, Index([1, 2, 3])) + + +def test_series_constructor(): + ser = Series([1, 2, 3]) + ser2 = Series(ser, index=ser) + ser2.iloc[0] = 0 + tm.assert_index_equal(ser2.index, Index([1, 2, 3])) + + +def test_dataframe_constructor(): + ser = Series([1, 2, 3]) + df = DataFrame({"a": ser}, index=ser) + ser.iloc[0] = 0 + tm.assert_index_equal(df.index, Index([1, 2, 3])) + df.iloc[0, 0] = 10 + tm.assert_index_equal(df.index, Index([1, 2, 3])) + + +def test_dataframe_set_index_inplace(): + df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6], "c": [0.1, 0.2, 0.3]}) + df.set_index("a", drop=False, inplace=True) + df.iloc[0, 0] = 0 + tm.assert_index_equal(df.index, Index([1, 2, 3], name="a")) + + +def test_index_attribute_assignment(): + ser = Series([1, 2, 3]) + ser.index = ser + ser.iloc[0] = 10 + tm.assert_index_equal(ser.index, Index([1, 2, 3])) diff --git a/pandas/tests/reductions/test_stat_reductions.py b/pandas/tests/reductions/test_stat_reductions.py index dd6aef04a2e6a..ce33f5279bdd0 100644 --- a/pandas/tests/reductions/test_stat_reductions.py +++ b/pandas/tests/reductions/test_stat_reductions.py @@ -77,6 +77,7 @@ def test_td64_mean(self, box): assert result == expected tdarr[0] = pd.NaT + obj = box(tdarr) assert obj.mean(skipna=False) is pd.NaT result2 = obj.mean(skipna=True)