Skip to content

Commit 83ea173

Browse files
authored
BUG: ArrayManager not respecting copy keyword (#44889)
1 parent e53bda9 commit 83ea173

File tree

5 files changed

+16
-44
lines changed

5 files changed

+16
-44
lines changed

pandas/core/internals/construction.py

+7-16
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
)
3636
from pandas.core.dtypes.common import (
3737
is_1d_only_ea_dtype,
38-
is_datetime64tz_dtype,
3938
is_datetime_or_timedelta_dtype,
4039
is_dtype_equal,
4140
is_extension_array_dtype,
@@ -44,7 +43,6 @@
4443
is_named_tuple,
4544
is_object_dtype,
4645
)
47-
from pandas.core.dtypes.dtypes import ExtensionDtype
4846
from pandas.core.dtypes.generic import (
4947
ABCDataFrame,
5048
ABCSeries,
@@ -475,23 +473,16 @@ def dict_to_mgr(
475473
keys = list(data.keys())
476474
columns = Index(keys)
477475
arrays = [com.maybe_iterable_to_list(data[k]) for k in keys]
478-
# GH#24096 need copy to be deep for datetime64tz case
479-
# TODO: See if we can avoid these copies
480476
arrays = [arr if not isinstance(arr, Index) else arr._data for arr in arrays]
481-
arrays = [
482-
arr if not is_datetime64tz_dtype(arr) else arr.copy() for arr in arrays
483-
]
484477

485478
if copy:
486-
# arrays_to_mgr (via form_blocks) won't make copies for EAs
487-
# dtype attr check to exclude EADtype-castable strs
488-
arrays = [
489-
x
490-
if not hasattr(x, "dtype") or not isinstance(x.dtype, ExtensionDtype)
491-
else x.copy()
492-
for x in arrays
493-
]
494-
# TODO: can we get rid of the dt64tz special case above?
479+
if typ == "block":
480+
# We only need to copy arrays that will not get consolidated, i.e.
481+
# only EA arrays
482+
arrays = [x.copy() if isinstance(x, ExtensionArray) else x for x in arrays]
483+
else:
484+
# dtype check to exclude e.g. range objects, scalars
485+
arrays = [x.copy() if hasattr(x, "dtype") else x for x in arrays]
495486

496487
return arrays_to_mgr(arrays, columns, index, dtype=dtype, typ=typ, consolidate=copy)
497488

pandas/tests/frame/indexing/test_setitem.py

-4
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,6 @@ def test_setitem_frame_duplicate_columns(self, using_array_manager, request):
421421
# TODO(ArrayManager) .loc still overwrites
422422
expected["B"] = expected["B"].astype("int64")
423423

424-
mark = pytest.mark.xfail(
425-
reason="Both 'A' columns get set with 3 instead of 0 and 3"
426-
)
427-
request.node.add_marker(mark)
428424
else:
429425
# set these with unique columns to be extra-unambiguous
430426
expected[2] = expected[2].astype(np.int64)

pandas/tests/frame/test_constructors.py

+4-9
Original file line numberDiff line numberDiff line change
@@ -2157,8 +2157,6 @@ def test_constructor_ndarray_copy(self, float_frame, using_array_manager):
21572157
arr[0, 0] = 1000
21582158
assert df.iloc[0, 0] == 1000
21592159

2160-
# TODO(ArrayManager) keep view on Series?
2161-
@td.skip_array_manager_not_yet_implemented
21622160
def test_constructor_series_copy(self, float_frame):
21632161
series = float_frame._series
21642162

@@ -2507,13 +2505,10 @@ def test_constructor_list_str_na(self, string_dtype):
25072505
def test_dict_nocopy(
25082506
self, request, copy, any_numeric_ea_dtype, any_numpy_dtype, using_array_manager
25092507
):
2510-
if using_array_manager and not (
2511-
(any_numpy_dtype in (tm.STRING_DTYPES + tm.BYTES_DTYPES))
2512-
or (
2513-
any_numpy_dtype
2514-
in (tm.DATETIME64_DTYPES + tm.TIMEDELTA64_DTYPES + tm.BOOL_DTYPES)
2515-
and copy
2516-
)
2508+
if (
2509+
using_array_manager
2510+
and not copy
2511+
and not (any_numpy_dtype in (tm.STRING_DTYPES + tm.BYTES_DTYPES))
25172512
):
25182513
# TODO(ArrayManager) properly honor copy keyword for dict input
25192514
td.mark_array_manager_not_yet_implemented(request)

pandas/tests/frame/test_reductions.py

+2-10
Original file line numberDiff line numberDiff line change
@@ -773,11 +773,7 @@ def test_operators_timedelta64(self):
773773
def test_std_timedelta64_skipna_false(self):
774774
# GH#37392
775775
tdi = pd.timedelta_range("1 Day", periods=10)
776-
df = DataFrame({"A": tdi, "B": tdi})
777-
# Copy is needed for ArrayManager case, otherwise setting df.iloc
778-
# below edits tdi, alterting both df['A'] and df['B']
779-
# FIXME: passing copy=True to constructor does not fix this
780-
df = df.copy()
776+
df = DataFrame({"A": tdi, "B": tdi}, copy=True)
781777
df.iloc[-2, -1] = pd.NaT
782778

783779
result = df.std(skipna=False)
@@ -1064,11 +1060,7 @@ def test_idxmax_idxmin_convert_dtypes(self, op, expected_value):
10641060

10651061
def test_idxmax_dt64_multicolumn_axis1(self):
10661062
dti = date_range("2016-01-01", periods=3)
1067-
df = DataFrame({3: dti, 4: dti[::-1]})
1068-
# FIXME: copy needed for ArrayManager, otherwise setting with iloc
1069-
# below also sets df.iloc[-1, 1]; passing copy=True to DataFrame
1070-
# does not solve this.
1071-
df = df.copy()
1063+
df = DataFrame({3: dti, 4: dti[::-1]}, copy=True)
10721064
df.iloc[0, 0] = pd.NaT
10731065

10741066
df._consolidate_inplace()

pandas/tests/indexing/multiindex/test_setitem.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,9 @@ def test_multiindex_assignment_single_dtype(self, using_array_manager):
214214
exp = Series(arr, index=[8, 10], name="c", dtype="int64")
215215
result = df.loc[4, "c"]
216216
tm.assert_series_equal(result, exp)
217-
if not using_array_manager:
218-
# FIXME(ArrayManager): this correctly preserves dtype,
219-
# but incorrectly is not inplace.
220-
# extra check for inplace-ness
221-
tm.assert_numpy_array_equal(view, exp.values)
217+
218+
# extra check for inplace-ness
219+
tm.assert_numpy_array_equal(view, exp.values)
222220

223221
# arr + 0.5 cannot be cast losslessly to int, so we upcast
224222
df.loc[4, "c"] = arr + 0.5

0 commit comments

Comments
 (0)