ZhengyangZhang commited on
Commit
5de2cea
·
verified ·
1 Parent(s): b02f7c5

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/__init__.cpython-312.pyc +0 -0
  2. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/common.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/conftest.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_alter_axes.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_api.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_arrow_interface.cpython-312.pyc +0 -0
  7. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_block_internals.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_cumulative.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_iteration.cpython-312.pyc +0 -0
  10. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_logical_ops.cpython-312.pyc +0 -0
  11. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_nonunique_indexes.cpython-312.pyc +0 -0
  12. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_npfuncs.cpython-312.pyc +0 -0
  13. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_query_eval.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_repr.cpython-312.pyc +0 -0
  15. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_subclass.cpython-312.pyc +0 -0
  16. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_ufunc.cpython-312.pyc +0 -0
  17. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_unary.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_validate.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/pandas/tests/frame/constructors/__init__.py +0 -0
  20. lib/python3.12/site-packages/pandas/tests/frame/constructors/__pycache__/__init__.cpython-312.pyc +0 -0
  21. lib/python3.12/site-packages/pandas/tests/frame/constructors/__pycache__/test_from_dict.cpython-312.pyc +0 -0
  22. lib/python3.12/site-packages/pandas/tests/frame/constructors/__pycache__/test_from_records.cpython-312.pyc +0 -0
  23. lib/python3.12/site-packages/pandas/tests/frame/constructors/test_from_dict.py +228 -0
  24. lib/python3.12/site-packages/pandas/tests/frame/constructors/test_from_records.py +505 -0
  25. lib/python3.12/site-packages/pandas/tests/frame/indexing/__init__.py +0 -0
  26. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/__init__.cpython-312.pyc +0 -0
  27. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_coercion.cpython-312.pyc +0 -0
  28. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_delitem.cpython-312.pyc +0 -0
  29. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_get.cpython-312.pyc +0 -0
  30. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_get_value.cpython-312.pyc +0 -0
  31. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_getitem.cpython-312.pyc +0 -0
  32. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_insert.cpython-312.pyc +0 -0
  33. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_mask.cpython-312.pyc +0 -0
  34. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_set_value.cpython-312.pyc +0 -0
  35. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_setitem.cpython-312.pyc +0 -0
  36. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_take.cpython-312.pyc +0 -0
  37. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_where.cpython-312.pyc +0 -0
  38. lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_xs.cpython-312.pyc +0 -0
  39. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_coercion.py +199 -0
  40. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_delitem.py +60 -0
  41. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_get.py +27 -0
  42. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_get_value.py +22 -0
  43. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_getitem.py +472 -0
  44. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_indexing.py +2024 -0
  45. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_insert.py +120 -0
  46. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_mask.py +152 -0
  47. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_set_value.py +77 -0
  48. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_setitem.py +1419 -0
  49. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_take.py +92 -0
  50. lib/python3.12/site-packages/pandas/tests/frame/indexing/test_where.py +1099 -0
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (197 Bytes). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/common.cpython-312.pyc ADDED
Binary file (3.24 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/conftest.cpython-312.pyc ADDED
Binary file (4.5 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_alter_axes.cpython-312.pyc ADDED
Binary file (1.67 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_api.cpython-312.pyc ADDED
Binary file (21.8 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_arrow_interface.cpython-312.pyc ADDED
Binary file (2.78 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_block_internals.cpython-312.pyc ADDED
Binary file (22.9 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_cumulative.cpython-312.pyc ADDED
Binary file (4.37 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_iteration.cpython-312.pyc ADDED
Binary file (9.34 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_logical_ops.cpython-312.pyc ADDED
Binary file (10.2 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_nonunique_indexes.cpython-312.pyc ADDED
Binary file (16.6 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_npfuncs.cpython-312.pyc ADDED
Binary file (4.4 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_query_eval.cpython-312.pyc ADDED
Binary file (90.1 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_repr.cpython-312.pyc ADDED
Binary file (27.3 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_subclass.cpython-312.pyc ADDED
Binary file (43.1 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_ufunc.cpython-312.pyc ADDED
Binary file (18.1 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_unary.cpython-312.pyc ADDED
Binary file (11 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/__pycache__/test_validate.cpython-312.pyc ADDED
Binary file (1.88 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/constructors/__init__.py ADDED
File without changes
lib/python3.12/site-packages/pandas/tests/frame/constructors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (210 Bytes). View file
 
lib/python3.12/site-packages/pandas/tests/frame/constructors/__pycache__/test_from_dict.cpython-312.pyc ADDED
Binary file (11.6 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/constructors/__pycache__/test_from_records.cpython-312.pyc ADDED
Binary file (31.2 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/constructors/test_from_dict.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import OrderedDict
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas._config import using_pyarrow_string_dtype
7
+
8
+ from pandas import (
9
+ DataFrame,
10
+ Index,
11
+ MultiIndex,
12
+ RangeIndex,
13
+ Series,
14
+ )
15
+ import pandas._testing as tm
16
+
17
+
18
+ class TestFromDict:
19
+ # Note: these tests are specific to the from_dict method, not for
20
+ # passing dictionaries to DataFrame.__init__
21
+
22
+ def test_constructor_list_of_odicts(self):
23
+ data = [
24
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4], ["d", 6]]),
25
+ OrderedDict([["a", 1.5], ["b", 3], ["d", 6]]),
26
+ OrderedDict([["a", 1.5], ["d", 6]]),
27
+ OrderedDict(),
28
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4]]),
29
+ OrderedDict([["b", 3], ["c", 4], ["d", 6]]),
30
+ ]
31
+
32
+ result = DataFrame(data)
33
+ expected = DataFrame.from_dict(
34
+ dict(zip(range(len(data)), data)), orient="index"
35
+ )
36
+ tm.assert_frame_equal(result, expected.reindex(result.index))
37
+
38
+ def test_constructor_single_row(self):
39
+ data = [OrderedDict([["a", 1.5], ["b", 3], ["c", 4], ["d", 6]])]
40
+
41
+ result = DataFrame(data)
42
+ expected = DataFrame.from_dict(dict(zip([0], data)), orient="index").reindex(
43
+ result.index
44
+ )
45
+ tm.assert_frame_equal(result, expected)
46
+
47
+ @pytest.mark.skipif(
48
+ using_pyarrow_string_dtype(), reason="columns inferring logic broken"
49
+ )
50
+ def test_constructor_list_of_series(self):
51
+ data = [
52
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 4.0]]),
53
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 6.0]]),
54
+ ]
55
+ sdict = OrderedDict(zip(["x", "y"], data))
56
+ idx = Index(["a", "b", "c"])
57
+
58
+ # all named
59
+ data2 = [
60
+ Series([1.5, 3, 4], idx, dtype="O", name="x"),
61
+ Series([1.5, 3, 6], idx, name="y"),
62
+ ]
63
+ result = DataFrame(data2)
64
+ expected = DataFrame.from_dict(sdict, orient="index")
65
+ tm.assert_frame_equal(result, expected)
66
+
67
+ # some unnamed
68
+ data2 = [
69
+ Series([1.5, 3, 4], idx, dtype="O", name="x"),
70
+ Series([1.5, 3, 6], idx),
71
+ ]
72
+ result = DataFrame(data2)
73
+
74
+ sdict = OrderedDict(zip(["x", "Unnamed 0"], data))
75
+ expected = DataFrame.from_dict(sdict, orient="index")
76
+ tm.assert_frame_equal(result, expected)
77
+
78
+ # none named
79
+ data = [
80
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4], ["d", 6]]),
81
+ OrderedDict([["a", 1.5], ["b", 3], ["d", 6]]),
82
+ OrderedDict([["a", 1.5], ["d", 6]]),
83
+ OrderedDict(),
84
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4]]),
85
+ OrderedDict([["b", 3], ["c", 4], ["d", 6]]),
86
+ ]
87
+ data = [Series(d) for d in data]
88
+
89
+ result = DataFrame(data)
90
+ sdict = OrderedDict(zip(range(len(data)), data))
91
+ expected = DataFrame.from_dict(sdict, orient="index")
92
+ tm.assert_frame_equal(result, expected.reindex(result.index))
93
+
94
+ result2 = DataFrame(data, index=np.arange(6, dtype=np.int64))
95
+ tm.assert_frame_equal(result, result2)
96
+
97
+ result = DataFrame([Series(dtype=object)])
98
+ expected = DataFrame(index=[0])
99
+ tm.assert_frame_equal(result, expected)
100
+
101
+ data = [
102
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 4.0]]),
103
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 6.0]]),
104
+ ]
105
+ sdict = OrderedDict(zip(range(len(data)), data))
106
+
107
+ idx = Index(["a", "b", "c"])
108
+ data2 = [Series([1.5, 3, 4], idx, dtype="O"), Series([1.5, 3, 6], idx)]
109
+ result = DataFrame(data2)
110
+ expected = DataFrame.from_dict(sdict, orient="index")
111
+ tm.assert_frame_equal(result, expected)
112
+
113
+ def test_constructor_orient(self, float_string_frame):
114
+ data_dict = float_string_frame.T._series
115
+ recons = DataFrame.from_dict(data_dict, orient="index")
116
+ expected = float_string_frame.reindex(index=recons.index)
117
+ tm.assert_frame_equal(recons, expected)
118
+
119
+ # dict of sequence
120
+ a = {"hi": [32, 3, 3], "there": [3, 5, 3]}
121
+ rs = DataFrame.from_dict(a, orient="index")
122
+ xp = DataFrame.from_dict(a).T.reindex(list(a.keys()))
123
+ tm.assert_frame_equal(rs, xp)
124
+
125
+ def test_constructor_from_ordered_dict(self):
126
+ # GH#8425
127
+ a = OrderedDict(
128
+ [
129
+ ("one", OrderedDict([("col_a", "foo1"), ("col_b", "bar1")])),
130
+ ("two", OrderedDict([("col_a", "foo2"), ("col_b", "bar2")])),
131
+ ("three", OrderedDict([("col_a", "foo3"), ("col_b", "bar3")])),
132
+ ]
133
+ )
134
+ expected = DataFrame.from_dict(a, orient="columns").T
135
+ result = DataFrame.from_dict(a, orient="index")
136
+ tm.assert_frame_equal(result, expected)
137
+
138
+ def test_from_dict_columns_parameter(self):
139
+ # GH#18529
140
+ # Test new columns parameter for from_dict that was added to make
141
+ # from_items(..., orient='index', columns=[...]) easier to replicate
142
+ result = DataFrame.from_dict(
143
+ OrderedDict([("A", [1, 2]), ("B", [4, 5])]),
144
+ orient="index",
145
+ columns=["one", "two"],
146
+ )
147
+ expected = DataFrame([[1, 2], [4, 5]], index=["A", "B"], columns=["one", "two"])
148
+ tm.assert_frame_equal(result, expected)
149
+
150
+ msg = "cannot use columns parameter with orient='columns'"
151
+ with pytest.raises(ValueError, match=msg):
152
+ DataFrame.from_dict(
153
+ {"A": [1, 2], "B": [4, 5]},
154
+ orient="columns",
155
+ columns=["one", "two"],
156
+ )
157
+ with pytest.raises(ValueError, match=msg):
158
+ DataFrame.from_dict({"A": [1, 2], "B": [4, 5]}, columns=["one", "two"])
159
+
160
+ @pytest.mark.parametrize(
161
+ "data_dict, orient, expected",
162
+ [
163
+ ({}, "index", RangeIndex(0)),
164
+ (
165
+ [{("a",): 1}, {("a",): 2}],
166
+ "columns",
167
+ Index([("a",)], tupleize_cols=False),
168
+ ),
169
+ (
170
+ [OrderedDict([(("a",), 1), (("b",), 2)])],
171
+ "columns",
172
+ Index([("a",), ("b",)], tupleize_cols=False),
173
+ ),
174
+ ([{("a", "b"): 1}], "columns", Index([("a", "b")], tupleize_cols=False)),
175
+ ],
176
+ )
177
+ def test_constructor_from_dict_tuples(self, data_dict, orient, expected):
178
+ # GH#16769
179
+ df = DataFrame.from_dict(data_dict, orient)
180
+ result = df.columns
181
+ tm.assert_index_equal(result, expected)
182
+
183
+ def test_frame_dict_constructor_empty_series(self):
184
+ s1 = Series(
185
+ [1, 2, 3, 4], index=MultiIndex.from_tuples([(1, 2), (1, 3), (2, 2), (2, 4)])
186
+ )
187
+ s2 = Series(
188
+ [1, 2, 3, 4], index=MultiIndex.from_tuples([(1, 2), (1, 3), (3, 2), (3, 4)])
189
+ )
190
+ s3 = Series(dtype=object)
191
+
192
+ # it works!
193
+ DataFrame({"foo": s1, "bar": s2, "baz": s3})
194
+ DataFrame.from_dict({"foo": s1, "baz": s3, "bar": s2})
195
+
196
+ def test_from_dict_scalars_requires_index(self):
197
+ msg = "If using all scalar values, you must pass an index"
198
+ with pytest.raises(ValueError, match=msg):
199
+ DataFrame.from_dict(OrderedDict([("b", 8), ("a", 5), ("a", 6)]))
200
+
201
+ def test_from_dict_orient_invalid(self):
202
+ msg = (
203
+ "Expected 'index', 'columns' or 'tight' for orient parameter. "
204
+ "Got 'abc' instead"
205
+ )
206
+ with pytest.raises(ValueError, match=msg):
207
+ DataFrame.from_dict({"foo": 1, "baz": 3, "bar": 2}, orient="abc")
208
+
209
+ def test_from_dict_order_with_single_column(self):
210
+ data = {
211
+ "alpha": {
212
+ "value2": 123,
213
+ "value1": 532,
214
+ "animal": 222,
215
+ "plant": False,
216
+ "name": "test",
217
+ }
218
+ }
219
+ result = DataFrame.from_dict(
220
+ data,
221
+ orient="columns",
222
+ )
223
+ expected = DataFrame(
224
+ [[123], [532], [222], [False], ["test"]],
225
+ index=["value2", "value1", "animal", "plant", "name"],
226
+ columns=["alpha"],
227
+ )
228
+ tm.assert_frame_equal(result, expected)
lib/python3.12/site-packages/pandas/tests/frame/constructors/test_from_records.py ADDED
@@ -0,0 +1,505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Iterator
2
+ from datetime import datetime
3
+ from decimal import Decimal
4
+
5
+ import numpy as np
6
+ import pytest
7
+ import pytz
8
+
9
+ from pandas._config import using_pyarrow_string_dtype
10
+
11
+ from pandas.compat import is_platform_little_endian
12
+
13
+ from pandas import (
14
+ CategoricalIndex,
15
+ DataFrame,
16
+ Index,
17
+ Interval,
18
+ RangeIndex,
19
+ Series,
20
+ date_range,
21
+ )
22
+ import pandas._testing as tm
23
+
24
+
25
+ class TestFromRecords:
26
+ def test_from_records_dt64tz_frame(self):
27
+ # GH#51162 don't lose tz when calling from_records with DataFrame input
28
+ dti = date_range("2016-01-01", periods=10, tz="US/Pacific")
29
+ df = DataFrame({i: dti for i in range(4)})
30
+ with tm.assert_produces_warning(FutureWarning):
31
+ res = DataFrame.from_records(df)
32
+ tm.assert_frame_equal(res, df)
33
+
34
+ def test_from_records_with_datetimes(self):
35
+ # this may fail on certain platforms because of a numpy issue
36
+ # related GH#6140
37
+ if not is_platform_little_endian():
38
+ pytest.skip("known failure of test on non-little endian")
39
+
40
+ # construction with a null in a recarray
41
+ # GH#6140
42
+ expected = DataFrame({"EXPIRY": [datetime(2005, 3, 1, 0, 0), None]})
43
+
44
+ arrdata = [np.array([datetime(2005, 3, 1, 0, 0), None])]
45
+ dtypes = [("EXPIRY", "<M8[ns]")]
46
+
47
+ recarray = np.rec.fromarrays(arrdata, dtype=dtypes)
48
+
49
+ result = DataFrame.from_records(recarray)
50
+ tm.assert_frame_equal(result, expected)
51
+
52
+ # coercion should work too
53
+ arrdata = [np.array([datetime(2005, 3, 1, 0, 0), None])]
54
+ dtypes = [("EXPIRY", "<M8[m]")]
55
+ recarray = np.rec.fromarrays(arrdata, dtype=dtypes)
56
+ result = DataFrame.from_records(recarray)
57
+ # we get the closest supported unit, "s"
58
+ expected["EXPIRY"] = expected["EXPIRY"].astype("M8[s]")
59
+ tm.assert_frame_equal(result, expected)
60
+
61
+ @pytest.mark.skipif(
62
+ using_pyarrow_string_dtype(), reason="dtype checking logic doesn't work"
63
+ )
64
+ def test_from_records_sequencelike(self):
65
+ df = DataFrame(
66
+ {
67
+ "A": np.array(
68
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
69
+ ),
70
+ "A1": np.array(
71
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
72
+ ),
73
+ "B": np.array(np.arange(6), dtype=np.int64),
74
+ "C": ["foo"] * 6,
75
+ "D": np.array([True, False] * 3, dtype=bool),
76
+ "E": np.array(
77
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
78
+ ),
79
+ "E1": np.array(
80
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
81
+ ),
82
+ "F": np.array(np.arange(6), dtype=np.int32),
83
+ }
84
+ )
85
+
86
+ # this is actually tricky to create the recordlike arrays and
87
+ # have the dtypes be intact
88
+ blocks = df._to_dict_of_blocks()
89
+ tuples = []
90
+ columns = []
91
+ dtypes = []
92
+ for dtype, b in blocks.items():
93
+ columns.extend(b.columns)
94
+ dtypes.extend([(c, np.dtype(dtype).descr[0][1]) for c in b.columns])
95
+ for i in range(len(df.index)):
96
+ tup = []
97
+ for _, b in blocks.items():
98
+ tup.extend(b.iloc[i].values)
99
+ tuples.append(tuple(tup))
100
+
101
+ recarray = np.array(tuples, dtype=dtypes).view(np.rec.recarray)
102
+ recarray2 = df.to_records()
103
+ lists = [list(x) for x in tuples]
104
+
105
+ # tuples (lose the dtype info)
106
+ result = DataFrame.from_records(tuples, columns=columns).reindex(
107
+ columns=df.columns
108
+ )
109
+
110
+ # created recarray and with to_records recarray (have dtype info)
111
+ result2 = DataFrame.from_records(recarray, columns=columns).reindex(
112
+ columns=df.columns
113
+ )
114
+ result3 = DataFrame.from_records(recarray2, columns=columns).reindex(
115
+ columns=df.columns
116
+ )
117
+
118
+ # list of tuples (no dtype info)
119
+ result4 = DataFrame.from_records(lists, columns=columns).reindex(
120
+ columns=df.columns
121
+ )
122
+
123
+ tm.assert_frame_equal(result, df, check_dtype=False)
124
+ tm.assert_frame_equal(result2, df)
125
+ tm.assert_frame_equal(result3, df)
126
+ tm.assert_frame_equal(result4, df, check_dtype=False)
127
+
128
+ # tuples is in the order of the columns
129
+ result = DataFrame.from_records(tuples)
130
+ tm.assert_index_equal(result.columns, RangeIndex(8))
131
+
132
+ # test exclude parameter & we are casting the results here (as we don't
133
+ # have dtype info to recover)
134
+ columns_to_test = [columns.index("C"), columns.index("E1")]
135
+
136
+ exclude = list(set(range(8)) - set(columns_to_test))
137
+ result = DataFrame.from_records(tuples, exclude=exclude)
138
+ result.columns = [columns[i] for i in sorted(columns_to_test)]
139
+ tm.assert_series_equal(result["C"], df["C"])
140
+ tm.assert_series_equal(result["E1"], df["E1"])
141
+
142
+ def test_from_records_sequencelike_empty(self):
143
+ # empty case
144
+ result = DataFrame.from_records([], columns=["foo", "bar", "baz"])
145
+ assert len(result) == 0
146
+ tm.assert_index_equal(result.columns, Index(["foo", "bar", "baz"]))
147
+
148
+ result = DataFrame.from_records([])
149
+ assert len(result) == 0
150
+ assert len(result.columns) == 0
151
+
152
+ def test_from_records_dictlike(self):
153
+ # test the dict methods
154
+ df = DataFrame(
155
+ {
156
+ "A": np.array(
157
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
158
+ ),
159
+ "A1": np.array(
160
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
161
+ ),
162
+ "B": np.array(np.arange(6), dtype=np.int64),
163
+ "C": ["foo"] * 6,
164
+ "D": np.array([True, False] * 3, dtype=bool),
165
+ "E": np.array(
166
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
167
+ ),
168
+ "E1": np.array(
169
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
170
+ ),
171
+ "F": np.array(np.arange(6), dtype=np.int32),
172
+ }
173
+ )
174
+
175
+ # columns is in a different order here than the actual items iterated
176
+ # from the dict
177
+ blocks = df._to_dict_of_blocks()
178
+ columns = []
179
+ for b in blocks.values():
180
+ columns.extend(b.columns)
181
+
182
+ asdict = dict(df.items())
183
+ asdict2 = {x: y.values for x, y in df.items()}
184
+
185
+ # dict of series & dict of ndarrays (have dtype info)
186
+ results = []
187
+ results.append(DataFrame.from_records(asdict).reindex(columns=df.columns))
188
+ results.append(
189
+ DataFrame.from_records(asdict, columns=columns).reindex(columns=df.columns)
190
+ )
191
+ results.append(
192
+ DataFrame.from_records(asdict2, columns=columns).reindex(columns=df.columns)
193
+ )
194
+
195
+ for r in results:
196
+ tm.assert_frame_equal(r, df)
197
+
198
+ def test_from_records_with_index_data(self):
199
+ df = DataFrame(
200
+ np.random.default_rng(2).standard_normal((10, 3)), columns=["A", "B", "C"]
201
+ )
202
+
203
+ data = np.random.default_rng(2).standard_normal(10)
204
+ with tm.assert_produces_warning(FutureWarning):
205
+ df1 = DataFrame.from_records(df, index=data)
206
+ tm.assert_index_equal(df1.index, Index(data))
207
+
208
+ def test_from_records_bad_index_column(self):
209
+ df = DataFrame(
210
+ np.random.default_rng(2).standard_normal((10, 3)), columns=["A", "B", "C"]
211
+ )
212
+
213
+ # should pass
214
+ with tm.assert_produces_warning(FutureWarning):
215
+ df1 = DataFrame.from_records(df, index=["C"])
216
+ tm.assert_index_equal(df1.index, Index(df.C))
217
+
218
+ with tm.assert_produces_warning(FutureWarning):
219
+ df1 = DataFrame.from_records(df, index="C")
220
+ tm.assert_index_equal(df1.index, Index(df.C))
221
+
222
+ # should fail
223
+ msg = "|".join(
224
+ [
225
+ r"'None of \[2\] are in the columns'",
226
+ ]
227
+ )
228
+ with pytest.raises(KeyError, match=msg):
229
+ with tm.assert_produces_warning(FutureWarning):
230
+ DataFrame.from_records(df, index=[2])
231
+ with pytest.raises(KeyError, match=msg):
232
+ with tm.assert_produces_warning(FutureWarning):
233
+ DataFrame.from_records(df, index=2)
234
+
235
+ def test_from_records_non_tuple(self):
236
+ class Record:
237
+ def __init__(self, *args) -> None:
238
+ self.args = args
239
+
240
+ def __getitem__(self, i):
241
+ return self.args[i]
242
+
243
+ def __iter__(self) -> Iterator:
244
+ return iter(self.args)
245
+
246
+ recs = [Record(1, 2, 3), Record(4, 5, 6), Record(7, 8, 9)]
247
+ tups = [tuple(rec) for rec in recs]
248
+
249
+ result = DataFrame.from_records(recs)
250
+ expected = DataFrame.from_records(tups)
251
+ tm.assert_frame_equal(result, expected)
252
+
253
+ def test_from_records_len0_with_columns(self):
254
+ # GH#2633
255
+ result = DataFrame.from_records([], index="foo", columns=["foo", "bar"])
256
+ expected = Index(["bar"])
257
+
258
+ assert len(result) == 0
259
+ assert result.index.name == "foo"
260
+ tm.assert_index_equal(result.columns, expected)
261
+
262
+ def test_from_records_series_list_dict(self):
263
+ # GH#27358
264
+ expected = DataFrame([[{"a": 1, "b": 2}, {"a": 3, "b": 4}]]).T
265
+ data = Series([[{"a": 1, "b": 2}], [{"a": 3, "b": 4}]])
266
+ result = DataFrame.from_records(data)
267
+ tm.assert_frame_equal(result, expected)
268
+
269
+ def test_from_records_series_categorical_index(self):
270
+ # GH#32805
271
+ index = CategoricalIndex(
272
+ [Interval(-20, -10), Interval(-10, 0), Interval(0, 10)]
273
+ )
274
+ series_of_dicts = Series([{"a": 1}, {"a": 2}, {"b": 3}], index=index)
275
+ frame = DataFrame.from_records(series_of_dicts, index=index)
276
+ expected = DataFrame(
277
+ {"a": [1, 2, np.nan], "b": [np.nan, np.nan, 3]}, index=index
278
+ )
279
+ tm.assert_frame_equal(frame, expected)
280
+
281
+ def test_frame_from_records_utc(self):
282
+ rec = {"datum": 1.5, "begin_time": datetime(2006, 4, 27, tzinfo=pytz.utc)}
283
+
284
+ # it works
285
+ DataFrame.from_records([rec], index="begin_time")
286
+
287
+ def test_from_records_to_records(self):
288
+ # from numpy documentation
289
+ arr = np.zeros((2,), dtype=("i4,f4,S10"))
290
+ arr[:] = [(1, 2.0, "Hello"), (2, 3.0, "World")]
291
+
292
+ DataFrame.from_records(arr)
293
+
294
+ index = Index(np.arange(len(arr))[::-1])
295
+ indexed_frame = DataFrame.from_records(arr, index=index)
296
+ tm.assert_index_equal(indexed_frame.index, index)
297
+
298
+ # without names, it should go to last ditch
299
+ arr2 = np.zeros((2, 3))
300
+ tm.assert_frame_equal(DataFrame.from_records(arr2), DataFrame(arr2))
301
+
302
+ # wrong length
303
+ msg = "|".join(
304
+ [
305
+ r"Length of values \(2\) does not match length of index \(1\)",
306
+ ]
307
+ )
308
+ with pytest.raises(ValueError, match=msg):
309
+ DataFrame.from_records(arr, index=index[:-1])
310
+
311
+ indexed_frame = DataFrame.from_records(arr, index="f1")
312
+
313
+ # what to do?
314
+ records = indexed_frame.to_records()
315
+ assert len(records.dtype.names) == 3
316
+
317
+ records = indexed_frame.to_records(index=False)
318
+ assert len(records.dtype.names) == 2
319
+ assert "index" not in records.dtype.names
320
+
321
+ def test_from_records_nones(self):
322
+ tuples = [(1, 2, None, 3), (1, 2, None, 3), (None, 2, 5, 3)]
323
+
324
+ df = DataFrame.from_records(tuples, columns=["a", "b", "c", "d"])
325
+ assert np.isnan(df["c"][0])
326
+
327
+ def test_from_records_iterator(self):
328
+ arr = np.array(
329
+ [(1.0, 1.0, 2, 2), (3.0, 3.0, 4, 4), (5.0, 5.0, 6, 6), (7.0, 7.0, 8, 8)],
330
+ dtype=[
331
+ ("x", np.float64),
332
+ ("u", np.float32),
333
+ ("y", np.int64),
334
+ ("z", np.int32),
335
+ ],
336
+ )
337
+ df = DataFrame.from_records(iter(arr), nrows=2)
338
+ xp = DataFrame(
339
+ {
340
+ "x": np.array([1.0, 3.0], dtype=np.float64),
341
+ "u": np.array([1.0, 3.0], dtype=np.float32),
342
+ "y": np.array([2, 4], dtype=np.int64),
343
+ "z": np.array([2, 4], dtype=np.int32),
344
+ }
345
+ )
346
+ tm.assert_frame_equal(df.reindex_like(xp), xp)
347
+
348
+ # no dtypes specified here, so just compare with the default
349
+ arr = [(1.0, 2), (3.0, 4), (5.0, 6), (7.0, 8)]
350
+ df = DataFrame.from_records(iter(arr), columns=["x", "y"], nrows=2)
351
+ tm.assert_frame_equal(df, xp.reindex(columns=["x", "y"]), check_dtype=False)
352
+
353
+ def test_from_records_tuples_generator(self):
354
+ def tuple_generator(length):
355
+ for i in range(length):
356
+ letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
357
+ yield (i, letters[i % len(letters)], i / length)
358
+
359
+ columns_names = ["Integer", "String", "Float"]
360
+ columns = [
361
+ [i[j] for i in tuple_generator(10)] for j in range(len(columns_names))
362
+ ]
363
+ data = {"Integer": columns[0], "String": columns[1], "Float": columns[2]}
364
+ expected = DataFrame(data, columns=columns_names)
365
+
366
+ generator = tuple_generator(10)
367
+ result = DataFrame.from_records(generator, columns=columns_names)
368
+ tm.assert_frame_equal(result, expected)
369
+
370
+ def test_from_records_lists_generator(self):
371
+ def list_generator(length):
372
+ for i in range(length):
373
+ letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
374
+ yield [i, letters[i % len(letters)], i / length]
375
+
376
+ columns_names = ["Integer", "String", "Float"]
377
+ columns = [
378
+ [i[j] for i in list_generator(10)] for j in range(len(columns_names))
379
+ ]
380
+ data = {"Integer": columns[0], "String": columns[1], "Float": columns[2]}
381
+ expected = DataFrame(data, columns=columns_names)
382
+
383
+ generator = list_generator(10)
384
+ result = DataFrame.from_records(generator, columns=columns_names)
385
+ tm.assert_frame_equal(result, expected)
386
+
387
+ def test_from_records_columns_not_modified(self):
388
+ tuples = [(1, 2, 3), (1, 2, 3), (2, 5, 3)]
389
+
390
+ columns = ["a", "b", "c"]
391
+ original_columns = list(columns)
392
+
393
+ DataFrame.from_records(tuples, columns=columns, index="a")
394
+
395
+ assert columns == original_columns
396
+
397
+ def test_from_records_decimal(self):
398
+ tuples = [(Decimal("1.5"),), (Decimal("2.5"),), (None,)]
399
+
400
+ df = DataFrame.from_records(tuples, columns=["a"])
401
+ assert df["a"].dtype == object
402
+
403
+ df = DataFrame.from_records(tuples, columns=["a"], coerce_float=True)
404
+ assert df["a"].dtype == np.float64
405
+ assert np.isnan(df["a"].values[-1])
406
+
407
+ def test_from_records_duplicates(self):
408
+ result = DataFrame.from_records([(1, 2, 3), (4, 5, 6)], columns=["a", "b", "a"])
409
+
410
+ expected = DataFrame([(1, 2, 3), (4, 5, 6)], columns=["a", "b", "a"])
411
+
412
+ tm.assert_frame_equal(result, expected)
413
+
414
+ def test_from_records_set_index_name(self):
415
+ def create_dict(order_id):
416
+ return {
417
+ "order_id": order_id,
418
+ "quantity": np.random.default_rng(2).integers(1, 10),
419
+ "price": np.random.default_rng(2).integers(1, 10),
420
+ }
421
+
422
+ documents = [create_dict(i) for i in range(10)]
423
+ # demo missing data
424
+ documents.append({"order_id": 10, "quantity": 5})
425
+
426
+ result = DataFrame.from_records(documents, index="order_id")
427
+ assert result.index.name == "order_id"
428
+
429
+ # MultiIndex
430
+ result = DataFrame.from_records(documents, index=["order_id", "quantity"])
431
+ assert result.index.names == ("order_id", "quantity")
432
+
433
+ def test_from_records_misc_brokenness(self):
434
+ # GH#2179
435
+
436
+ data = {1: ["foo"], 2: ["bar"]}
437
+
438
+ result = DataFrame.from_records(data, columns=["a", "b"])
439
+ exp = DataFrame(data, columns=["a", "b"])
440
+ tm.assert_frame_equal(result, exp)
441
+
442
+ # overlap in index/index_names
443
+
444
+ data = {"a": [1, 2, 3], "b": [4, 5, 6]}
445
+
446
+ result = DataFrame.from_records(data, index=["a", "b", "c"])
447
+ exp = DataFrame(data, index=["a", "b", "c"])
448
+ tm.assert_frame_equal(result, exp)
449
+
450
+ def test_from_records_misc_brokenness2(self):
451
+ # GH#2623
452
+ rows = []
453
+ rows.append([datetime(2010, 1, 1), 1])
454
+ rows.append([datetime(2010, 1, 2), "hi"]) # test col upconverts to obj
455
+ result = DataFrame.from_records(rows, columns=["date", "test"])
456
+ expected = DataFrame(
457
+ {"date": [row[0] for row in rows], "test": [row[1] for row in rows]}
458
+ )
459
+ tm.assert_frame_equal(result, expected)
460
+ assert result.dtypes["test"] == np.dtype(object)
461
+
462
+ def test_from_records_misc_brokenness3(self):
463
+ rows = []
464
+ rows.append([datetime(2010, 1, 1), 1])
465
+ rows.append([datetime(2010, 1, 2), 1])
466
+ result = DataFrame.from_records(rows, columns=["date", "test"])
467
+ expected = DataFrame(
468
+ {"date": [row[0] for row in rows], "test": [row[1] for row in rows]}
469
+ )
470
+ tm.assert_frame_equal(result, expected)
471
+
472
+ def test_from_records_empty(self):
473
+ # GH#3562
474
+ result = DataFrame.from_records([], columns=["a", "b", "c"])
475
+ expected = DataFrame(columns=["a", "b", "c"])
476
+ tm.assert_frame_equal(result, expected)
477
+
478
+ result = DataFrame.from_records([], columns=["a", "b", "b"])
479
+ expected = DataFrame(columns=["a", "b", "b"])
480
+ tm.assert_frame_equal(result, expected)
481
+
482
+ def test_from_records_empty_with_nonempty_fields_gh3682(self):
483
+ a = np.array([(1, 2)], dtype=[("id", np.int64), ("value", np.int64)])
484
+ df = DataFrame.from_records(a, index="id")
485
+
486
+ ex_index = Index([1], name="id")
487
+ expected = DataFrame({"value": [2]}, index=ex_index, columns=["value"])
488
+ tm.assert_frame_equal(df, expected)
489
+
490
+ b = a[:0]
491
+ df2 = DataFrame.from_records(b, index="id")
492
+ tm.assert_frame_equal(df2, df.iloc[:0])
493
+
494
+ def test_from_records_empty2(self):
495
+ # GH#42456
496
+ dtype = [("prop", int)]
497
+ shape = (0, len(dtype))
498
+ arr = np.empty(shape, dtype=dtype)
499
+
500
+ result = DataFrame.from_records(arr)
501
+ expected = DataFrame({"prop": np.array([], dtype=int)})
502
+ tm.assert_frame_equal(result, expected)
503
+
504
+ alt = DataFrame(arr)
505
+ tm.assert_frame_equal(alt, expected)
lib/python3.12/site-packages/pandas/tests/frame/indexing/__init__.py ADDED
File without changes
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (206 Bytes). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_coercion.cpython-312.pyc ADDED
Binary file (9.98 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_delitem.cpython-312.pyc ADDED
Binary file (3.49 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_get.cpython-312.pyc ADDED
Binary file (1.45 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_get_value.cpython-312.pyc ADDED
Binary file (1.53 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_getitem.cpython-312.pyc ADDED
Binary file (24.4 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_insert.cpython-312.pyc ADDED
Binary file (7.15 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_mask.cpython-312.pyc ADDED
Binary file (9.86 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_set_value.cpython-312.pyc ADDED
Binary file (4.49 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_setitem.cpython-312.pyc ADDED
Binary file (81.8 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_take.cpython-312.pyc ADDED
Binary file (5.38 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_where.cpython-312.pyc ADDED
Binary file (61 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/__pycache__/test_xs.cpython-312.pyc ADDED
Binary file (22.9 kB). View file
 
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_coercion.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for values coercion in setitem-like operations on DataFrame.
3
+
4
+ For the most part, these should be multi-column DataFrames, otherwise
5
+ we would share the tests with Series.
6
+ """
7
+ import numpy as np
8
+ import pytest
9
+
10
+ import pandas as pd
11
+ from pandas import (
12
+ DataFrame,
13
+ MultiIndex,
14
+ NaT,
15
+ Series,
16
+ Timestamp,
17
+ date_range,
18
+ )
19
+ import pandas._testing as tm
20
+
21
+
22
+ class TestDataFrameSetitemCoercion:
23
+ @pytest.mark.parametrize("consolidate", [True, False])
24
+ def test_loc_setitem_multiindex_columns(self, consolidate):
25
+ # GH#18415 Setting values in a single column preserves dtype,
26
+ # while setting them in multiple columns did unwanted cast.
27
+
28
+ # Note that A here has 2 blocks, below we do the same thing
29
+ # with a consolidated frame.
30
+ A = DataFrame(np.zeros((6, 5), dtype=np.float32))
31
+ A = pd.concat([A, A], axis=1, keys=[1, 2])
32
+ if consolidate:
33
+ A = A._consolidate()
34
+
35
+ A.loc[2:3, (1, slice(2, 3))] = np.ones((2, 2), dtype=np.float32)
36
+ assert (A.dtypes == np.float32).all()
37
+
38
+ A.loc[0:5, (1, slice(2, 3))] = np.ones((6, 2), dtype=np.float32)
39
+
40
+ assert (A.dtypes == np.float32).all()
41
+
42
+ A.loc[:, (1, slice(2, 3))] = np.ones((6, 2), dtype=np.float32)
43
+ assert (A.dtypes == np.float32).all()
44
+
45
+ # TODO: i think this isn't about MultiIndex and could be done with iloc?
46
+
47
+
48
+ def test_37477():
49
+ # fixed by GH#45121
50
+ orig = DataFrame({"A": [1, 2, 3], "B": [3, 4, 5]})
51
+ expected = DataFrame({"A": [1, 2, 3], "B": [3, 1.2, 5]})
52
+
53
+ df = orig.copy()
54
+ with tm.assert_produces_warning(
55
+ FutureWarning, match="Setting an item of incompatible dtype"
56
+ ):
57
+ df.at[1, "B"] = 1.2
58
+ tm.assert_frame_equal(df, expected)
59
+
60
+ df = orig.copy()
61
+ with tm.assert_produces_warning(
62
+ FutureWarning, match="Setting an item of incompatible dtype"
63
+ ):
64
+ df.loc[1, "B"] = 1.2
65
+ tm.assert_frame_equal(df, expected)
66
+
67
+ df = orig.copy()
68
+ with tm.assert_produces_warning(
69
+ FutureWarning, match="Setting an item of incompatible dtype"
70
+ ):
71
+ df.iat[1, 1] = 1.2
72
+ tm.assert_frame_equal(df, expected)
73
+
74
+ df = orig.copy()
75
+ with tm.assert_produces_warning(
76
+ FutureWarning, match="Setting an item of incompatible dtype"
77
+ ):
78
+ df.iloc[1, 1] = 1.2
79
+ tm.assert_frame_equal(df, expected)
80
+
81
+
82
+ def test_6942(indexer_al):
83
+ # check that the .at __setitem__ after setting "Live" actually sets the data
84
+ start = Timestamp("2014-04-01")
85
+ t1 = Timestamp("2014-04-23 12:42:38.883082")
86
+ t2 = Timestamp("2014-04-24 01:33:30.040039")
87
+
88
+ dti = date_range(start, periods=1)
89
+ orig = DataFrame(index=dti, columns=["timenow", "Live"])
90
+
91
+ df = orig.copy()
92
+ indexer_al(df)[start, "timenow"] = t1
93
+
94
+ df["Live"] = True
95
+
96
+ df.at[start, "timenow"] = t2
97
+ assert df.iloc[0, 0] == t2
98
+
99
+
100
+ def test_26395(indexer_al):
101
+ # .at case fixed by GH#45121 (best guess)
102
+ df = DataFrame(index=["A", "B", "C"])
103
+ df["D"] = 0
104
+
105
+ indexer_al(df)["C", "D"] = 2
106
+ expected = DataFrame({"D": [0, 0, 2]}, index=["A", "B", "C"], dtype=np.int64)
107
+ tm.assert_frame_equal(df, expected)
108
+
109
+ with tm.assert_produces_warning(
110
+ FutureWarning, match="Setting an item of incompatible dtype"
111
+ ):
112
+ indexer_al(df)["C", "D"] = 44.5
113
+ expected = DataFrame({"D": [0, 0, 44.5]}, index=["A", "B", "C"], dtype=np.float64)
114
+ tm.assert_frame_equal(df, expected)
115
+
116
+ with tm.assert_produces_warning(
117
+ FutureWarning, match="Setting an item of incompatible dtype"
118
+ ):
119
+ indexer_al(df)["C", "D"] = "hello"
120
+ expected = DataFrame({"D": [0, 0, "hello"]}, index=["A", "B", "C"], dtype=object)
121
+ tm.assert_frame_equal(df, expected)
122
+
123
+
124
+ @pytest.mark.xfail(reason="unwanted upcast")
125
+ def test_15231():
126
+ df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
127
+ df.loc[2] = Series({"a": 5, "b": 6})
128
+ assert (df.dtypes == np.int64).all()
129
+
130
+ df.loc[3] = Series({"a": 7})
131
+
132
+ # df["a"] doesn't have any NaNs, should not have been cast
133
+ exp_dtypes = Series([np.int64, np.float64], dtype=object, index=["a", "b"])
134
+ tm.assert_series_equal(df.dtypes, exp_dtypes)
135
+
136
+
137
+ def test_iloc_setitem_unnecesssary_float_upcasting():
138
+ # GH#12255
139
+ df = DataFrame(
140
+ {
141
+ 0: np.array([1, 3], dtype=np.float32),
142
+ 1: np.array([2, 4], dtype=np.float32),
143
+ 2: ["a", "b"],
144
+ }
145
+ )
146
+ orig = df.copy()
147
+
148
+ values = df[0].values.reshape(2, 1)
149
+ df.iloc[:, 0:1] = values
150
+
151
+ tm.assert_frame_equal(df, orig)
152
+
153
+
154
+ @pytest.mark.xfail(reason="unwanted casting to dt64")
155
+ def test_12499():
156
+ # TODO: OP in GH#12499 used np.datetim64("NaT") instead of pd.NaT,
157
+ # which has consequences for the expected df["two"] (though i think at
158
+ # the time it might not have because of a separate bug). See if it makes
159
+ # a difference which one we use here.
160
+ ts = Timestamp("2016-03-01 03:13:22.98986", tz="UTC")
161
+
162
+ data = [{"one": 0, "two": ts}]
163
+ orig = DataFrame(data)
164
+ df = orig.copy()
165
+ df.loc[1] = [np.nan, NaT]
166
+
167
+ expected = DataFrame(
168
+ {"one": [0, np.nan], "two": Series([ts, NaT], dtype="datetime64[ns, UTC]")}
169
+ )
170
+ tm.assert_frame_equal(df, expected)
171
+
172
+ data = [{"one": 0, "two": ts}]
173
+ df = orig.copy()
174
+ df.loc[1, :] = [np.nan, NaT]
175
+ tm.assert_frame_equal(df, expected)
176
+
177
+
178
+ def test_20476():
179
+ mi = MultiIndex.from_product([["A", "B"], ["a", "b", "c"]])
180
+ df = DataFrame(-1, index=range(3), columns=mi)
181
+ filler = DataFrame([[1, 2, 3.0]] * 3, index=range(3), columns=["a", "b", "c"])
182
+ df["A"] = filler
183
+
184
+ expected = DataFrame(
185
+ {
186
+ 0: [1, 1, 1],
187
+ 1: [2, 2, 2],
188
+ 2: [3.0, 3.0, 3.0],
189
+ 3: [-1, -1, -1],
190
+ 4: [-1, -1, -1],
191
+ 5: [-1, -1, -1],
192
+ }
193
+ )
194
+ expected.columns = mi
195
+ exp_dtypes = Series(
196
+ [np.dtype(np.int64)] * 2 + [np.dtype(np.float64)] + [np.dtype(np.int64)] * 3,
197
+ index=mi,
198
+ )
199
+ tm.assert_series_equal(df.dtypes, exp_dtypes)
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_delitem.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas import (
7
+ DataFrame,
8
+ MultiIndex,
9
+ )
10
+
11
+
12
+ class TestDataFrameDelItem:
13
+ def test_delitem(self, float_frame):
14
+ del float_frame["A"]
15
+ assert "A" not in float_frame
16
+
17
+ def test_delitem_multiindex(self):
18
+ midx = MultiIndex.from_product([["A", "B"], [1, 2]])
19
+ df = DataFrame(np.random.default_rng(2).standard_normal((4, 4)), columns=midx)
20
+ assert len(df.columns) == 4
21
+ assert ("A",) in df.columns
22
+ assert "A" in df.columns
23
+
24
+ result = df["A"]
25
+ assert isinstance(result, DataFrame)
26
+ del df["A"]
27
+
28
+ assert len(df.columns) == 2
29
+
30
+ # A still in the levels, BUT get a KeyError if trying
31
+ # to delete
32
+ assert ("A",) not in df.columns
33
+ with pytest.raises(KeyError, match=re.escape("('A',)")):
34
+ del df[("A",)]
35
+
36
+ # behavior of dropped/deleted MultiIndex levels changed from
37
+ # GH 2770 to GH 19027: MultiIndex no longer '.__contains__'
38
+ # levels which are dropped/deleted
39
+ assert "A" not in df.columns
40
+ with pytest.raises(KeyError, match=re.escape("('A',)")):
41
+ del df["A"]
42
+
43
+ def test_delitem_corner(self, float_frame):
44
+ f = float_frame.copy()
45
+ del f["D"]
46
+ assert len(f.columns) == 3
47
+ with pytest.raises(KeyError, match=r"^'D'$"):
48
+ del f["D"]
49
+ del f["B"]
50
+ assert len(f.columns) == 2
51
+
52
+ def test_delitem_col_still_multiindex(self):
53
+ arrays = [["a", "b", "c", "top"], ["", "", "", "OD"], ["", "", "", "wx"]]
54
+
55
+ tuples = sorted(zip(*arrays))
56
+ index = MultiIndex.from_tuples(tuples)
57
+
58
+ df = DataFrame(np.random.default_rng(2).standard_normal((3, 4)), columns=index)
59
+ del df[("a", "", "")]
60
+ assert isinstance(df.columns, MultiIndex)
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_get.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas import DataFrame
4
+ import pandas._testing as tm
5
+
6
+
7
+ class TestGet:
8
+ def test_get(self, float_frame):
9
+ b = float_frame.get("B")
10
+ tm.assert_series_equal(b, float_frame["B"])
11
+
12
+ assert float_frame.get("foo") is None
13
+ tm.assert_series_equal(
14
+ float_frame.get("foo", float_frame["B"]), float_frame["B"]
15
+ )
16
+
17
+ @pytest.mark.parametrize(
18
+ "df",
19
+ [
20
+ DataFrame(),
21
+ DataFrame(columns=list("AB")),
22
+ DataFrame(columns=list("AB"), index=range(3)),
23
+ ],
24
+ )
25
+ def test_get_none(self, df):
26
+ # see gh-5652
27
+ assert df.get(None) is None
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_get_value.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas import (
4
+ DataFrame,
5
+ MultiIndex,
6
+ )
7
+
8
+
9
+ class TestGetValue:
10
+ def test_get_set_value_no_partial_indexing(self):
11
+ # partial w/ MultiIndex raise exception
12
+ index = MultiIndex.from_tuples([(0, 1), (0, 2), (1, 1), (1, 2)])
13
+ df = DataFrame(index=index, columns=range(4))
14
+ with pytest.raises(KeyError, match=r"^0$"):
15
+ df._get_value(0, 1)
16
+
17
+ def test_get_value(self, float_frame):
18
+ for idx in float_frame.index:
19
+ for col in float_frame.columns:
20
+ result = float_frame._get_value(idx, col)
21
+ expected = float_frame[col][idx]
22
+ assert result == expected
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_getitem.py ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas import (
7
+ Categorical,
8
+ CategoricalDtype,
9
+ CategoricalIndex,
10
+ DataFrame,
11
+ DateOffset,
12
+ DatetimeIndex,
13
+ Index,
14
+ MultiIndex,
15
+ Series,
16
+ Timestamp,
17
+ concat,
18
+ date_range,
19
+ get_dummies,
20
+ period_range,
21
+ )
22
+ import pandas._testing as tm
23
+ from pandas.core.arrays import SparseArray
24
+
25
+
26
+ class TestGetitem:
27
+ def test_getitem_unused_level_raises(self):
28
+ # GH#20410
29
+ mi = MultiIndex(
30
+ levels=[["a_lot", "onlyone", "notevenone"], [1970, ""]],
31
+ codes=[[1, 0], [1, 0]],
32
+ )
33
+ df = DataFrame(-1, index=range(3), columns=mi)
34
+
35
+ with pytest.raises(KeyError, match="notevenone"):
36
+ df["notevenone"]
37
+
38
+ def test_getitem_periodindex(self):
39
+ rng = period_range("1/1/2000", periods=5)
40
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 5)), columns=rng)
41
+
42
+ ts = df[rng[0]]
43
+ tm.assert_series_equal(ts, df.iloc[:, 0])
44
+
45
+ ts = df["1/1/2000"]
46
+ tm.assert_series_equal(ts, df.iloc[:, 0])
47
+
48
+ def test_getitem_list_of_labels_categoricalindex_cols(self):
49
+ # GH#16115
50
+ cats = Categorical([Timestamp("12-31-1999"), Timestamp("12-31-2000")])
51
+
52
+ expected = DataFrame([[1, 0], [0, 1]], dtype="bool", index=[0, 1], columns=cats)
53
+ dummies = get_dummies(cats)
54
+ result = dummies[list(dummies.columns)]
55
+ tm.assert_frame_equal(result, expected)
56
+
57
+ def test_getitem_sparse_column_return_type_and_dtype(self):
58
+ # https://github.com/pandas-dev/pandas/issues/23559
59
+ data = SparseArray([0, 1])
60
+ df = DataFrame({"A": data})
61
+ expected = Series(data, name="A")
62
+ result = df["A"]
63
+ tm.assert_series_equal(result, expected)
64
+
65
+ # Also check iloc and loc while we're here
66
+ result = df.iloc[:, 0]
67
+ tm.assert_series_equal(result, expected)
68
+
69
+ result = df.loc[:, "A"]
70
+ tm.assert_series_equal(result, expected)
71
+
72
+ def test_getitem_string_columns(self):
73
+ # GH#46185
74
+ df = DataFrame([[1, 2]], columns=Index(["A", "B"], dtype="string"))
75
+ result = df.A
76
+ expected = df["A"]
77
+ tm.assert_series_equal(result, expected)
78
+
79
+
80
+ class TestGetitemListLike:
81
+ def test_getitem_list_missing_key(self):
82
+ # GH#13822, incorrect error string with non-unique columns when missing
83
+ # column is accessed
84
+ df = DataFrame({"x": [1.0], "y": [2.0], "z": [3.0]})
85
+ df.columns = ["x", "x", "z"]
86
+
87
+ # Check that we get the correct value in the KeyError
88
+ with pytest.raises(KeyError, match=r"\['y'\] not in index"):
89
+ df[["x", "y", "z"]]
90
+
91
+ def test_getitem_list_duplicates(self):
92
+ # GH#1943
93
+ df = DataFrame(
94
+ np.random.default_rng(2).standard_normal((4, 4)), columns=list("AABC")
95
+ )
96
+ df.columns.name = "foo"
97
+
98
+ result = df[["B", "C"]]
99
+ assert result.columns.name == "foo"
100
+
101
+ expected = df.iloc[:, 2:]
102
+ tm.assert_frame_equal(result, expected)
103
+
104
+ def test_getitem_dupe_cols(self):
105
+ df = DataFrame([[1, 2, 3], [4, 5, 6]], columns=["a", "a", "b"])
106
+ msg = "\"None of [Index(['baf'], dtype="
107
+ with pytest.raises(KeyError, match=re.escape(msg)):
108
+ df[["baf"]]
109
+
110
+ @pytest.mark.parametrize(
111
+ "idx_type",
112
+ [
113
+ list,
114
+ iter,
115
+ Index,
116
+ set,
117
+ lambda keys: dict(zip(keys, range(len(keys)))),
118
+ lambda keys: dict(zip(keys, range(len(keys)))).keys(),
119
+ ],
120
+ ids=["list", "iter", "Index", "set", "dict", "dict_keys"],
121
+ )
122
+ @pytest.mark.parametrize("levels", [1, 2])
123
+ def test_getitem_listlike(self, idx_type, levels, float_frame):
124
+ # GH#21294
125
+
126
+ if levels == 1:
127
+ frame, missing = float_frame, "food"
128
+ else:
129
+ # MultiIndex columns
130
+ frame = DataFrame(
131
+ np.random.default_rng(2).standard_normal((8, 3)),
132
+ columns=Index(
133
+ [("foo", "bar"), ("baz", "qux"), ("peek", "aboo")],
134
+ name=("sth", "sth2"),
135
+ ),
136
+ )
137
+ missing = ("good", "food")
138
+
139
+ keys = [frame.columns[1], frame.columns[0]]
140
+ idx = idx_type(keys)
141
+ idx_check = list(idx_type(keys))
142
+
143
+ if isinstance(idx, (set, dict)):
144
+ with pytest.raises(TypeError, match="as an indexer is not supported"):
145
+ frame[idx]
146
+
147
+ return
148
+ else:
149
+ result = frame[idx]
150
+
151
+ expected = frame.loc[:, idx_check]
152
+ expected.columns.names = frame.columns.names
153
+
154
+ tm.assert_frame_equal(result, expected)
155
+
156
+ idx = idx_type(keys + [missing])
157
+ with pytest.raises(KeyError, match="not in index"):
158
+ frame[idx]
159
+
160
+ def test_getitem_iloc_generator(self):
161
+ # GH#39614
162
+ df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
163
+ indexer = (x for x in [1, 2])
164
+ result = df.iloc[indexer]
165
+ expected = DataFrame({"a": [2, 3], "b": [5, 6]}, index=[1, 2])
166
+ tm.assert_frame_equal(result, expected)
167
+
168
+ def test_getitem_iloc_two_dimensional_generator(self):
169
+ df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
170
+ indexer = (x for x in [1, 2])
171
+ result = df.iloc[indexer, 1]
172
+ expected = Series([5, 6], name="b", index=[1, 2])
173
+ tm.assert_series_equal(result, expected)
174
+
175
+ def test_getitem_iloc_dateoffset_days(self):
176
+ # GH 46671
177
+ df = DataFrame(
178
+ list(range(10)),
179
+ index=date_range("01-01-2022", periods=10, freq=DateOffset(days=1)),
180
+ )
181
+ result = df.loc["2022-01-01":"2022-01-03"]
182
+ expected = DataFrame(
183
+ [0, 1, 2],
184
+ index=DatetimeIndex(
185
+ ["2022-01-01", "2022-01-02", "2022-01-03"],
186
+ dtype="datetime64[ns]",
187
+ freq=DateOffset(days=1),
188
+ ),
189
+ )
190
+ tm.assert_frame_equal(result, expected)
191
+
192
+ df = DataFrame(
193
+ list(range(10)),
194
+ index=date_range(
195
+ "01-01-2022", periods=10, freq=DateOffset(days=1, hours=2)
196
+ ),
197
+ )
198
+ result = df.loc["2022-01-01":"2022-01-03"]
199
+ expected = DataFrame(
200
+ [0, 1, 2],
201
+ index=DatetimeIndex(
202
+ ["2022-01-01 00:00:00", "2022-01-02 02:00:00", "2022-01-03 04:00:00"],
203
+ dtype="datetime64[ns]",
204
+ freq=DateOffset(days=1, hours=2),
205
+ ),
206
+ )
207
+ tm.assert_frame_equal(result, expected)
208
+
209
+ df = DataFrame(
210
+ list(range(10)),
211
+ index=date_range("01-01-2022", periods=10, freq=DateOffset(minutes=3)),
212
+ )
213
+ result = df.loc["2022-01-01":"2022-01-03"]
214
+ tm.assert_frame_equal(result, df)
215
+
216
+
217
+ class TestGetitemCallable:
218
+ def test_getitem_callable(self, float_frame):
219
+ # GH#12533
220
+ result = float_frame[lambda x: "A"]
221
+ expected = float_frame.loc[:, "A"]
222
+ tm.assert_series_equal(result, expected)
223
+
224
+ result = float_frame[lambda x: ["A", "B"]]
225
+ expected = float_frame.loc[:, ["A", "B"]]
226
+ tm.assert_frame_equal(result, float_frame.loc[:, ["A", "B"]])
227
+
228
+ df = float_frame[:3]
229
+ result = df[lambda x: [True, False, True]]
230
+ expected = float_frame.iloc[[0, 2], :]
231
+ tm.assert_frame_equal(result, expected)
232
+
233
+ def test_loc_multiindex_columns_one_level(self):
234
+ # GH#29749
235
+ df = DataFrame([[1, 2]], columns=[["a", "b"]])
236
+ expected = DataFrame([1], columns=[["a"]])
237
+
238
+ result = df["a"]
239
+ tm.assert_frame_equal(result, expected)
240
+
241
+ result = df.loc[:, "a"]
242
+ tm.assert_frame_equal(result, expected)
243
+
244
+
245
+ class TestGetitemBooleanMask:
246
+ def test_getitem_bool_mask_categorical_index(self):
247
+ df3 = DataFrame(
248
+ {
249
+ "A": np.arange(6, dtype="int64"),
250
+ },
251
+ index=CategoricalIndex(
252
+ [1, 1, 2, 1, 3, 2],
253
+ dtype=CategoricalDtype([3, 2, 1], ordered=True),
254
+ name="B",
255
+ ),
256
+ )
257
+ df4 = DataFrame(
258
+ {
259
+ "A": np.arange(6, dtype="int64"),
260
+ },
261
+ index=CategoricalIndex(
262
+ [1, 1, 2, 1, 3, 2],
263
+ dtype=CategoricalDtype([3, 2, 1], ordered=False),
264
+ name="B",
265
+ ),
266
+ )
267
+
268
+ result = df3[df3.index == "a"]
269
+ expected = df3.iloc[[]]
270
+ tm.assert_frame_equal(result, expected)
271
+
272
+ result = df4[df4.index == "a"]
273
+ expected = df4.iloc[[]]
274
+ tm.assert_frame_equal(result, expected)
275
+
276
+ result = df3[df3.index == 1]
277
+ expected = df3.iloc[[0, 1, 3]]
278
+ tm.assert_frame_equal(result, expected)
279
+
280
+ result = df4[df4.index == 1]
281
+ expected = df4.iloc[[0, 1, 3]]
282
+ tm.assert_frame_equal(result, expected)
283
+
284
+ # since we have an ordered categorical
285
+
286
+ # CategoricalIndex([1, 1, 2, 1, 3, 2],
287
+ # categories=[3, 2, 1],
288
+ # ordered=True,
289
+ # name='B')
290
+ result = df3[df3.index < 2]
291
+ expected = df3.iloc[[4]]
292
+ tm.assert_frame_equal(result, expected)
293
+
294
+ result = df3[df3.index > 1]
295
+ expected = df3.iloc[[]]
296
+ tm.assert_frame_equal(result, expected)
297
+
298
+ # unordered
299
+ # cannot be compared
300
+
301
+ # CategoricalIndex([1, 1, 2, 1, 3, 2],
302
+ # categories=[3, 2, 1],
303
+ # ordered=False,
304
+ # name='B')
305
+ msg = "Unordered Categoricals can only compare equality or not"
306
+ with pytest.raises(TypeError, match=msg):
307
+ df4[df4.index < 2]
308
+ with pytest.raises(TypeError, match=msg):
309
+ df4[df4.index > 1]
310
+
311
+ @pytest.mark.parametrize(
312
+ "data1,data2,expected_data",
313
+ (
314
+ (
315
+ [[1, 2], [3, 4]],
316
+ [[0.5, 6], [7, 8]],
317
+ [[np.nan, 3.0], [np.nan, 4.0], [np.nan, 7.0], [6.0, 8.0]],
318
+ ),
319
+ (
320
+ [[1, 2], [3, 4]],
321
+ [[5, 6], [7, 8]],
322
+ [[np.nan, 3.0], [np.nan, 4.0], [5, 7], [6, 8]],
323
+ ),
324
+ ),
325
+ )
326
+ def test_getitem_bool_mask_duplicate_columns_mixed_dtypes(
327
+ self,
328
+ data1,
329
+ data2,
330
+ expected_data,
331
+ ):
332
+ # GH#31954
333
+
334
+ df1 = DataFrame(np.array(data1))
335
+ df2 = DataFrame(np.array(data2))
336
+ df = concat([df1, df2], axis=1)
337
+
338
+ result = df[df > 2]
339
+
340
+ exdict = {i: np.array(col) for i, col in enumerate(expected_data)}
341
+ expected = DataFrame(exdict).rename(columns={2: 0, 3: 1})
342
+ tm.assert_frame_equal(result, expected)
343
+
344
+ @pytest.fixture
345
+ def df_dup_cols(self):
346
+ dups = ["A", "A", "C", "D"]
347
+ df = DataFrame(np.arange(12).reshape(3, 4), columns=dups, dtype="float64")
348
+ return df
349
+
350
+ def test_getitem_boolean_frame_unaligned_with_duplicate_columns(self, df_dup_cols):
351
+ # `df.A > 6` is a DataFrame with a different shape from df
352
+
353
+ # boolean with the duplicate raises
354
+ df = df_dup_cols
355
+ msg = "cannot reindex on an axis with duplicate labels"
356
+ with pytest.raises(ValueError, match=msg):
357
+ df[df.A > 6]
358
+
359
+ def test_getitem_boolean_series_with_duplicate_columns(self, df_dup_cols):
360
+ # boolean indexing
361
+ # GH#4879
362
+ df = DataFrame(
363
+ np.arange(12).reshape(3, 4), columns=["A", "B", "C", "D"], dtype="float64"
364
+ )
365
+ expected = df[df.C > 6]
366
+ expected.columns = df_dup_cols.columns
367
+
368
+ df = df_dup_cols
369
+ result = df[df.C > 6]
370
+
371
+ tm.assert_frame_equal(result, expected)
372
+
373
+ def test_getitem_boolean_frame_with_duplicate_columns(self, df_dup_cols):
374
+ # where
375
+ df = DataFrame(
376
+ np.arange(12).reshape(3, 4), columns=["A", "B", "C", "D"], dtype="float64"
377
+ )
378
+ # `df > 6` is a DataFrame with the same shape+alignment as df
379
+ expected = df[df > 6]
380
+ expected.columns = df_dup_cols.columns
381
+
382
+ df = df_dup_cols
383
+ result = df[df > 6]
384
+
385
+ tm.assert_frame_equal(result, expected)
386
+
387
+ def test_getitem_empty_frame_with_boolean(self):
388
+ # Test for issue GH#11859
389
+
390
+ df = DataFrame()
391
+ df2 = df[df > 0]
392
+ tm.assert_frame_equal(df, df2)
393
+
394
+ def test_getitem_returns_view_when_column_is_unique_in_df(
395
+ self, using_copy_on_write, warn_copy_on_write
396
+ ):
397
+ # GH#45316
398
+ df = DataFrame([[1, 2, 3], [4, 5, 6]], columns=["a", "a", "b"])
399
+ df_orig = df.copy()
400
+ view = df["b"]
401
+ with tm.assert_cow_warning(warn_copy_on_write):
402
+ view.loc[:] = 100
403
+ if using_copy_on_write:
404
+ expected = df_orig
405
+ else:
406
+ expected = DataFrame([[1, 2, 100], [4, 5, 100]], columns=["a", "a", "b"])
407
+ tm.assert_frame_equal(df, expected)
408
+
409
+ def test_getitem_frozenset_unique_in_column(self):
410
+ # GH#41062
411
+ df = DataFrame([[1, 2, 3, 4]], columns=[frozenset(["KEY"]), "B", "C", "C"])
412
+ result = df[frozenset(["KEY"])]
413
+ expected = Series([1], name=frozenset(["KEY"]))
414
+ tm.assert_series_equal(result, expected)
415
+
416
+
417
+ class TestGetitemSlice:
418
+ def test_getitem_slice_float64(self, frame_or_series):
419
+ values = np.arange(10.0, 50.0, 2)
420
+ index = Index(values)
421
+
422
+ start, end = values[[5, 15]]
423
+
424
+ data = np.random.default_rng(2).standard_normal((20, 3))
425
+ if frame_or_series is not DataFrame:
426
+ data = data[:, 0]
427
+
428
+ obj = frame_or_series(data, index=index)
429
+
430
+ result = obj[start:end]
431
+ expected = obj.iloc[5:16]
432
+ tm.assert_equal(result, expected)
433
+
434
+ result = obj.loc[start:end]
435
+ tm.assert_equal(result, expected)
436
+
437
+ def test_getitem_datetime_slice(self):
438
+ # GH#43223
439
+ df = DataFrame(
440
+ {"a": 0},
441
+ index=DatetimeIndex(
442
+ [
443
+ "11.01.2011 22:00",
444
+ "11.01.2011 23:00",
445
+ "12.01.2011 00:00",
446
+ "2011-01-13 00:00",
447
+ ]
448
+ ),
449
+ )
450
+ with pytest.raises(
451
+ KeyError, match="Value based partial slicing on non-monotonic"
452
+ ):
453
+ df["2011-01-01":"2011-11-01"]
454
+
455
+ def test_getitem_slice_same_dim_only_one_axis(self):
456
+ # GH#54622
457
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 8)))
458
+ result = df.iloc[(slice(None, None, 2),)]
459
+ assert result.shape == (5, 8)
460
+ expected = df.iloc[slice(None, None, 2), slice(None)]
461
+ tm.assert_frame_equal(result, expected)
462
+
463
+
464
+ class TestGetitemDeprecatedIndexers:
465
+ @pytest.mark.parametrize("key", [{"a", "b"}, {"a": "a"}])
466
+ def test_getitem_dict_and_set_deprecated(self, key):
467
+ # GH#42825 enforced in 2.0
468
+ df = DataFrame(
469
+ [[1, 2], [3, 4]], columns=MultiIndex.from_tuples([("a", 1), ("b", 2)])
470
+ )
471
+ with pytest.raises(TypeError, match="as an indexer is not supported"):
472
+ df[key]
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_indexing.py ADDED
@@ -0,0 +1,2024 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import namedtuple
2
+ from datetime import (
3
+ datetime,
4
+ timedelta,
5
+ )
6
+ from decimal import Decimal
7
+ import re
8
+
9
+ import numpy as np
10
+ import pytest
11
+
12
+ from pandas._libs import iNaT
13
+ from pandas.errors import (
14
+ InvalidIndexError,
15
+ PerformanceWarning,
16
+ SettingWithCopyError,
17
+ )
18
+ import pandas.util._test_decorators as td
19
+
20
+ from pandas.core.dtypes.common import is_integer
21
+
22
+ import pandas as pd
23
+ from pandas import (
24
+ Categorical,
25
+ DataFrame,
26
+ DatetimeIndex,
27
+ Index,
28
+ MultiIndex,
29
+ Series,
30
+ Timestamp,
31
+ date_range,
32
+ isna,
33
+ notna,
34
+ to_datetime,
35
+ )
36
+ import pandas._testing as tm
37
+
38
+ # We pass through a TypeError raised by numpy
39
+ _slice_msg = "slice indices must be integers or None or have an __index__ method"
40
+
41
+
42
+ class TestDataFrameIndexing:
43
+ def test_getitem(self, float_frame):
44
+ # Slicing
45
+ sl = float_frame[:20]
46
+ assert len(sl.index) == 20
47
+
48
+ # Column access
49
+ for _, series in sl.items():
50
+ assert len(series.index) == 20
51
+ tm.assert_index_equal(series.index, sl.index)
52
+
53
+ for key, _ in float_frame._series.items():
54
+ assert float_frame[key] is not None
55
+
56
+ assert "random" not in float_frame
57
+ with pytest.raises(KeyError, match="random"):
58
+ float_frame["random"]
59
+
60
+ def test_getitem_numeric_should_not_fallback_to_positional(self, any_numeric_dtype):
61
+ # GH51053
62
+ dtype = any_numeric_dtype
63
+ idx = Index([1, 0, 1], dtype=dtype)
64
+ df = DataFrame([[1, 2, 3], [4, 5, 6]], columns=idx)
65
+ result = df[1]
66
+ expected = DataFrame([[1, 3], [4, 6]], columns=Index([1, 1], dtype=dtype))
67
+ tm.assert_frame_equal(result, expected, check_exact=True)
68
+
69
+ def test_getitem2(self, float_frame):
70
+ df = float_frame.copy()
71
+ df["$10"] = np.random.default_rng(2).standard_normal(len(df))
72
+
73
+ ad = np.random.default_rng(2).standard_normal(len(df))
74
+ df["@awesome_domain"] = ad
75
+
76
+ with pytest.raises(KeyError, match=re.escape("'df[\"$10\"]'")):
77
+ df.__getitem__('df["$10"]')
78
+
79
+ res = df["@awesome_domain"]
80
+ tm.assert_numpy_array_equal(ad, res.values)
81
+
82
+ def test_setitem_numeric_should_not_fallback_to_positional(self, any_numeric_dtype):
83
+ # GH51053
84
+ dtype = any_numeric_dtype
85
+ idx = Index([1, 0, 1], dtype=dtype)
86
+ df = DataFrame([[1, 2, 3], [4, 5, 6]], columns=idx)
87
+ df[1] = 10
88
+ expected = DataFrame([[10, 2, 10], [10, 5, 10]], columns=idx)
89
+ tm.assert_frame_equal(df, expected, check_exact=True)
90
+
91
+ def test_setitem_list(self, float_frame):
92
+ float_frame["E"] = "foo"
93
+ data = float_frame[["A", "B"]]
94
+ float_frame[["B", "A"]] = data
95
+
96
+ tm.assert_series_equal(float_frame["B"], data["A"], check_names=False)
97
+ tm.assert_series_equal(float_frame["A"], data["B"], check_names=False)
98
+
99
+ msg = "Columns must be same length as key"
100
+ with pytest.raises(ValueError, match=msg):
101
+ data[["A"]] = float_frame[["A", "B"]]
102
+ newcolumndata = range(len(data.index) - 1)
103
+ msg = (
104
+ rf"Length of values \({len(newcolumndata)}\) "
105
+ rf"does not match length of index \({len(data)}\)"
106
+ )
107
+ with pytest.raises(ValueError, match=msg):
108
+ data["A"] = newcolumndata
109
+
110
+ def test_setitem_list2(self):
111
+ df = DataFrame(0, index=range(3), columns=["tt1", "tt2"], dtype=int)
112
+ df.loc[1, ["tt1", "tt2"]] = [1, 2]
113
+
114
+ result = df.loc[df.index[1], ["tt1", "tt2"]]
115
+ expected = Series([1, 2], df.columns, dtype=int, name=1)
116
+ tm.assert_series_equal(result, expected)
117
+
118
+ df["tt1"] = df["tt2"] = "0"
119
+ df.loc[df.index[1], ["tt1", "tt2"]] = ["1", "2"]
120
+ result = df.loc[df.index[1], ["tt1", "tt2"]]
121
+ expected = Series(["1", "2"], df.columns, name=1)
122
+ tm.assert_series_equal(result, expected)
123
+
124
+ def test_getitem_boolean(self, mixed_float_frame, mixed_int_frame, datetime_frame):
125
+ # boolean indexing
126
+ d = datetime_frame.index[10]
127
+ indexer = datetime_frame.index > d
128
+ indexer_obj = indexer.astype(object)
129
+
130
+ subindex = datetime_frame.index[indexer]
131
+ subframe = datetime_frame[indexer]
132
+
133
+ tm.assert_index_equal(subindex, subframe.index)
134
+ with pytest.raises(ValueError, match="Item wrong length"):
135
+ datetime_frame[indexer[:-1]]
136
+
137
+ subframe_obj = datetime_frame[indexer_obj]
138
+ tm.assert_frame_equal(subframe_obj, subframe)
139
+
140
+ with pytest.raises(ValueError, match="Boolean array expected"):
141
+ datetime_frame[datetime_frame]
142
+
143
+ # test that Series work
144
+ indexer_obj = Series(indexer_obj, datetime_frame.index)
145
+
146
+ subframe_obj = datetime_frame[indexer_obj]
147
+ tm.assert_frame_equal(subframe_obj, subframe)
148
+
149
+ # test that Series indexers reindex
150
+ # we are producing a warning that since the passed boolean
151
+ # key is not the same as the given index, we will reindex
152
+ # not sure this is really necessary
153
+ with tm.assert_produces_warning(UserWarning):
154
+ indexer_obj = indexer_obj.reindex(datetime_frame.index[::-1])
155
+ subframe_obj = datetime_frame[indexer_obj]
156
+ tm.assert_frame_equal(subframe_obj, subframe)
157
+
158
+ # test df[df > 0]
159
+ for df in [
160
+ datetime_frame,
161
+ mixed_float_frame,
162
+ mixed_int_frame,
163
+ ]:
164
+ data = df._get_numeric_data()
165
+ bif = df[df > 0]
166
+ bifw = DataFrame(
167
+ {c: np.where(data[c] > 0, data[c], np.nan) for c in data.columns},
168
+ index=data.index,
169
+ columns=data.columns,
170
+ )
171
+
172
+ # add back other columns to compare
173
+ for c in df.columns:
174
+ if c not in bifw:
175
+ bifw[c] = df[c]
176
+ bifw = bifw.reindex(columns=df.columns)
177
+
178
+ tm.assert_frame_equal(bif, bifw, check_dtype=False)
179
+ for c in df.columns:
180
+ if bif[c].dtype != bifw[c].dtype:
181
+ assert bif[c].dtype == df[c].dtype
182
+
183
+ def test_getitem_boolean_casting(self, datetime_frame):
184
+ # don't upcast if we don't need to
185
+ df = datetime_frame.copy()
186
+ df["E"] = 1
187
+ df["E"] = df["E"].astype("int32")
188
+ df["E1"] = df["E"].copy()
189
+ df["F"] = 1
190
+ df["F"] = df["F"].astype("int64")
191
+ df["F1"] = df["F"].copy()
192
+
193
+ casted = df[df > 0]
194
+ result = casted.dtypes
195
+ expected = Series(
196
+ [np.dtype("float64")] * 4
197
+ + [np.dtype("int32")] * 2
198
+ + [np.dtype("int64")] * 2,
199
+ index=["A", "B", "C", "D", "E", "E1", "F", "F1"],
200
+ )
201
+ tm.assert_series_equal(result, expected)
202
+
203
+ # int block splitting
204
+ df.loc[df.index[1:3], ["E1", "F1"]] = 0
205
+ casted = df[df > 0]
206
+ result = casted.dtypes
207
+ expected = Series(
208
+ [np.dtype("float64")] * 4
209
+ + [np.dtype("int32")]
210
+ + [np.dtype("float64")]
211
+ + [np.dtype("int64")]
212
+ + [np.dtype("float64")],
213
+ index=["A", "B", "C", "D", "E", "E1", "F", "F1"],
214
+ )
215
+ tm.assert_series_equal(result, expected)
216
+
217
+ @pytest.mark.parametrize(
218
+ "lst", [[True, False, True], [True, True, True], [False, False, False]]
219
+ )
220
+ def test_getitem_boolean_list(self, lst):
221
+ df = DataFrame(np.arange(12).reshape(3, 4))
222
+ result = df[lst]
223
+ expected = df.loc[df.index[lst]]
224
+ tm.assert_frame_equal(result, expected)
225
+
226
+ def test_getitem_boolean_iadd(self):
227
+ arr = np.random.default_rng(2).standard_normal((5, 5))
228
+
229
+ df = DataFrame(arr.copy(), columns=["A", "B", "C", "D", "E"])
230
+
231
+ df[df < 0] += 1
232
+ arr[arr < 0] += 1
233
+
234
+ tm.assert_almost_equal(df.values, arr)
235
+
236
+ def test_boolean_index_empty_corner(self):
237
+ # #2096
238
+ blah = DataFrame(np.empty([0, 1]), columns=["A"], index=DatetimeIndex([]))
239
+
240
+ # both of these should succeed trivially
241
+ k = np.array([], bool)
242
+
243
+ blah[k]
244
+ blah[k] = 0
245
+
246
+ def test_getitem_ix_mixed_integer(self):
247
+ df = DataFrame(
248
+ np.random.default_rng(2).standard_normal((4, 3)),
249
+ index=[1, 10, "C", "E"],
250
+ columns=[1, 2, 3],
251
+ )
252
+
253
+ result = df.iloc[:-1]
254
+ expected = df.loc[df.index[:-1]]
255
+ tm.assert_frame_equal(result, expected)
256
+
257
+ result = df.loc[[1, 10]]
258
+ expected = df.loc[Index([1, 10])]
259
+ tm.assert_frame_equal(result, expected)
260
+
261
+ def test_getitem_ix_mixed_integer2(self):
262
+ # 11320
263
+ df = DataFrame(
264
+ {
265
+ "rna": (1.5, 2.2, 3.2, 4.5),
266
+ -1000: [11, 21, 36, 40],
267
+ 0: [10, 22, 43, 34],
268
+ 1000: [0, 10, 20, 30],
269
+ },
270
+ columns=["rna", -1000, 0, 1000],
271
+ )
272
+ result = df[[1000]]
273
+ expected = df.iloc[:, [3]]
274
+ tm.assert_frame_equal(result, expected)
275
+ result = df[[-1000]]
276
+ expected = df.iloc[:, [1]]
277
+ tm.assert_frame_equal(result, expected)
278
+
279
+ def test_getattr(self, float_frame):
280
+ tm.assert_series_equal(float_frame.A, float_frame["A"])
281
+ msg = "'DataFrame' object has no attribute 'NONEXISTENT_NAME'"
282
+ with pytest.raises(AttributeError, match=msg):
283
+ float_frame.NONEXISTENT_NAME
284
+
285
+ def test_setattr_column(self):
286
+ df = DataFrame({"foobar": 1}, index=range(10))
287
+
288
+ df.foobar = 5
289
+ assert (df.foobar == 5).all()
290
+
291
+ def test_setitem(
292
+ self, float_frame, using_copy_on_write, warn_copy_on_write, using_infer_string
293
+ ):
294
+ # not sure what else to do here
295
+ series = float_frame["A"][::2]
296
+ float_frame["col5"] = series
297
+ assert "col5" in float_frame
298
+
299
+ assert len(series) == 15
300
+ assert len(float_frame) == 30
301
+
302
+ exp = np.ravel(np.column_stack((series.values, [np.nan] * 15)))
303
+ exp = Series(exp, index=float_frame.index, name="col5")
304
+ tm.assert_series_equal(float_frame["col5"], exp)
305
+
306
+ series = float_frame["A"]
307
+ float_frame["col6"] = series
308
+ tm.assert_series_equal(series, float_frame["col6"], check_names=False)
309
+
310
+ # set ndarray
311
+ arr = np.random.default_rng(2).standard_normal(len(float_frame))
312
+ float_frame["col9"] = arr
313
+ assert (float_frame["col9"] == arr).all()
314
+
315
+ float_frame["col7"] = 5
316
+ assert (float_frame["col7"] == 5).all()
317
+
318
+ float_frame["col0"] = 3.14
319
+ assert (float_frame["col0"] == 3.14).all()
320
+
321
+ float_frame["col8"] = "foo"
322
+ assert (float_frame["col8"] == "foo").all()
323
+
324
+ # this is partially a view (e.g. some blocks are view)
325
+ # so raise/warn
326
+ smaller = float_frame[:2]
327
+
328
+ msg = r"\nA value is trying to be set on a copy of a slice from a DataFrame"
329
+ if using_copy_on_write or warn_copy_on_write:
330
+ # With CoW, adding a new column doesn't raise a warning
331
+ smaller["col10"] = ["1", "2"]
332
+ else:
333
+ with pytest.raises(SettingWithCopyError, match=msg):
334
+ smaller["col10"] = ["1", "2"]
335
+
336
+ if using_infer_string:
337
+ assert smaller["col10"].dtype == "string"
338
+ else:
339
+ assert smaller["col10"].dtype == np.object_
340
+ assert (smaller["col10"] == ["1", "2"]).all()
341
+
342
+ def test_setitem2(self):
343
+ # dtype changing GH4204
344
+ df = DataFrame([[0, 0]])
345
+ df.iloc[0] = np.nan
346
+ expected = DataFrame([[np.nan, np.nan]])
347
+ tm.assert_frame_equal(df, expected)
348
+
349
+ df = DataFrame([[0, 0]])
350
+ df.loc[0] = np.nan
351
+ tm.assert_frame_equal(df, expected)
352
+
353
+ def test_setitem_boolean(self, float_frame):
354
+ df = float_frame.copy()
355
+ values = float_frame.values.copy()
356
+
357
+ df[df["A"] > 0] = 4
358
+ values[values[:, 0] > 0] = 4
359
+ tm.assert_almost_equal(df.values, values)
360
+
361
+ # test that column reindexing works
362
+ series = df["A"] == 4
363
+ series = series.reindex(df.index[::-1])
364
+ df[series] = 1
365
+ values[values[:, 0] == 4] = 1
366
+ tm.assert_almost_equal(df.values, values)
367
+
368
+ df[df > 0] = 5
369
+ values[values > 0] = 5
370
+ tm.assert_almost_equal(df.values, values)
371
+
372
+ df[df == 5] = 0
373
+ values[values == 5] = 0
374
+ tm.assert_almost_equal(df.values, values)
375
+
376
+ # a df that needs alignment first
377
+ df[df[:-1] < 0] = 2
378
+ np.putmask(values[:-1], values[:-1] < 0, 2)
379
+ tm.assert_almost_equal(df.values, values)
380
+
381
+ # indexed with same shape but rows-reversed df
382
+ df[df[::-1] == 2] = 3
383
+ values[values == 2] = 3
384
+ tm.assert_almost_equal(df.values, values)
385
+
386
+ msg = "Must pass DataFrame or 2-d ndarray with boolean values only"
387
+ with pytest.raises(TypeError, match=msg):
388
+ df[df * 0] = 2
389
+
390
+ # index with DataFrame
391
+ df_orig = df.copy()
392
+ mask = df > np.abs(df)
393
+ df[df > np.abs(df)] = np.nan
394
+ values = df_orig.values.copy()
395
+ values[mask.values] = np.nan
396
+ expected = DataFrame(values, index=df_orig.index, columns=df_orig.columns)
397
+ tm.assert_frame_equal(df, expected)
398
+
399
+ # set from DataFrame
400
+ df[df > np.abs(df)] = df * 2
401
+ np.putmask(values, mask.values, df.values * 2)
402
+ expected = DataFrame(values, index=df_orig.index, columns=df_orig.columns)
403
+ tm.assert_frame_equal(df, expected)
404
+
405
+ def test_setitem_cast(self, float_frame):
406
+ float_frame["D"] = float_frame["D"].astype("i8")
407
+ assert float_frame["D"].dtype == np.int64
408
+
409
+ # #669, should not cast?
410
+ # this is now set to int64, which means a replacement of the column to
411
+ # the value dtype (and nothing to do with the existing dtype)
412
+ float_frame["B"] = 0
413
+ assert float_frame["B"].dtype == np.int64
414
+
415
+ # cast if pass array of course
416
+ float_frame["B"] = np.arange(len(float_frame))
417
+ assert issubclass(float_frame["B"].dtype.type, np.integer)
418
+
419
+ float_frame["foo"] = "bar"
420
+ float_frame["foo"] = 0
421
+ assert float_frame["foo"].dtype == np.int64
422
+
423
+ float_frame["foo"] = "bar"
424
+ float_frame["foo"] = 2.5
425
+ assert float_frame["foo"].dtype == np.float64
426
+
427
+ float_frame["something"] = 0
428
+ assert float_frame["something"].dtype == np.int64
429
+ float_frame["something"] = 2
430
+ assert float_frame["something"].dtype == np.int64
431
+ float_frame["something"] = 2.5
432
+ assert float_frame["something"].dtype == np.float64
433
+
434
+ def test_setitem_corner(self, float_frame, using_infer_string):
435
+ # corner case
436
+ df = DataFrame({"B": [1.0, 2.0, 3.0], "C": ["a", "b", "c"]}, index=np.arange(3))
437
+ del df["B"]
438
+ df["B"] = [1.0, 2.0, 3.0]
439
+ assert "B" in df
440
+ assert len(df.columns) == 2
441
+
442
+ df["A"] = "beginning"
443
+ df["E"] = "foo"
444
+ df["D"] = "bar"
445
+ df[datetime.now()] = "date"
446
+ df[datetime.now()] = 5.0
447
+
448
+ # what to do when empty frame with index
449
+ dm = DataFrame(index=float_frame.index)
450
+ dm["A"] = "foo"
451
+ dm["B"] = "bar"
452
+ assert len(dm.columns) == 2
453
+ assert dm.values.dtype == np.object_
454
+
455
+ # upcast
456
+ dm["C"] = 1
457
+ assert dm["C"].dtype == np.int64
458
+
459
+ dm["E"] = 1.0
460
+ assert dm["E"].dtype == np.float64
461
+
462
+ # set existing column
463
+ dm["A"] = "bar"
464
+ assert "bar" == dm["A"].iloc[0]
465
+
466
+ dm = DataFrame(index=np.arange(3))
467
+ dm["A"] = 1
468
+ dm["foo"] = "bar"
469
+ del dm["foo"]
470
+ dm["foo"] = "bar"
471
+ if using_infer_string:
472
+ assert dm["foo"].dtype == "string"
473
+ else:
474
+ assert dm["foo"].dtype == np.object_
475
+
476
+ dm["coercible"] = ["1", "2", "3"]
477
+ if using_infer_string:
478
+ assert dm["coercible"].dtype == "string"
479
+ else:
480
+ assert dm["coercible"].dtype == np.object_
481
+
482
+ def test_setitem_corner2(self):
483
+ data = {
484
+ "title": ["foobar", "bar", "foobar"] + ["foobar"] * 17,
485
+ "cruft": np.random.default_rng(2).random(20),
486
+ }
487
+
488
+ df = DataFrame(data)
489
+ ix = df[df["title"] == "bar"].index
490
+
491
+ df.loc[ix, ["title"]] = "foobar"
492
+ df.loc[ix, ["cruft"]] = 0
493
+
494
+ assert df.loc[1, "title"] == "foobar"
495
+ assert df.loc[1, "cruft"] == 0
496
+
497
+ def test_setitem_ambig(self, using_infer_string):
498
+ # Difficulties with mixed-type data
499
+ # Created as float type
500
+ dm = DataFrame(index=range(3), columns=range(3))
501
+
502
+ coercable_series = Series([Decimal(1) for _ in range(3)], index=range(3))
503
+ uncoercable_series = Series(["foo", "bzr", "baz"], index=range(3))
504
+
505
+ dm[0] = np.ones(3)
506
+ assert len(dm.columns) == 3
507
+
508
+ dm[1] = coercable_series
509
+ assert len(dm.columns) == 3
510
+
511
+ dm[2] = uncoercable_series
512
+ assert len(dm.columns) == 3
513
+ if using_infer_string:
514
+ assert dm[2].dtype == "string"
515
+ else:
516
+ assert dm[2].dtype == np.object_
517
+
518
+ def test_setitem_None(self, float_frame, using_infer_string):
519
+ # GH #766
520
+ float_frame[None] = float_frame["A"]
521
+ key = None if not using_infer_string else np.nan
522
+ tm.assert_series_equal(
523
+ float_frame.iloc[:, -1], float_frame["A"], check_names=False
524
+ )
525
+ tm.assert_series_equal(
526
+ float_frame.loc[:, key], float_frame["A"], check_names=False
527
+ )
528
+ tm.assert_series_equal(float_frame[key], float_frame["A"], check_names=False)
529
+
530
+ def test_loc_setitem_boolean_mask_allfalse(self):
531
+ # GH 9596
532
+ df = DataFrame(
533
+ {"a": ["1", "2", "3"], "b": ["11", "22", "33"], "c": ["111", "222", "333"]}
534
+ )
535
+
536
+ result = df.copy()
537
+ result.loc[result.b.isna(), "a"] = result.a.copy()
538
+ tm.assert_frame_equal(result, df)
539
+
540
+ def test_getitem_fancy_slice_integers_step(self):
541
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 5)))
542
+
543
+ # this is OK
544
+ df.iloc[:8:2]
545
+ df.iloc[:8:2] = np.nan
546
+ assert isna(df.iloc[:8:2]).values.all()
547
+
548
+ def test_getitem_setitem_integer_slice_keyerrors(self):
549
+ df = DataFrame(
550
+ np.random.default_rng(2).standard_normal((10, 5)), index=range(0, 20, 2)
551
+ )
552
+
553
+ # this is OK
554
+ cp = df.copy()
555
+ cp.iloc[4:10] = 0
556
+ assert (cp.iloc[4:10] == 0).values.all()
557
+
558
+ # so is this
559
+ cp = df.copy()
560
+ cp.iloc[3:11] = 0
561
+ assert (cp.iloc[3:11] == 0).values.all()
562
+
563
+ result = df.iloc[2:6]
564
+ result2 = df.loc[3:11]
565
+ expected = df.reindex([4, 6, 8, 10])
566
+
567
+ tm.assert_frame_equal(result, expected)
568
+ tm.assert_frame_equal(result2, expected)
569
+
570
+ # non-monotonic, raise KeyError
571
+ df2 = df.iloc[list(range(5)) + list(range(5, 10))[::-1]]
572
+ with pytest.raises(KeyError, match=r"^3$"):
573
+ df2.loc[3:11]
574
+ with pytest.raises(KeyError, match=r"^3$"):
575
+ df2.loc[3:11] = 0
576
+
577
+ @td.skip_array_manager_invalid_test # already covered in test_iloc_col_slice_view
578
+ def test_fancy_getitem_slice_mixed(
579
+ self, float_frame, float_string_frame, using_copy_on_write, warn_copy_on_write
580
+ ):
581
+ sliced = float_string_frame.iloc[:, -3:]
582
+ assert sliced["D"].dtype == np.float64
583
+
584
+ # get view with single block
585
+ # setting it triggers setting with copy
586
+ original = float_frame.copy()
587
+ sliced = float_frame.iloc[:, -3:]
588
+
589
+ assert np.shares_memory(sliced["C"]._values, float_frame["C"]._values)
590
+
591
+ with tm.assert_cow_warning(warn_copy_on_write):
592
+ sliced.loc[:, "C"] = 4.0
593
+ if not using_copy_on_write:
594
+ assert (float_frame["C"] == 4).all()
595
+
596
+ # with the enforcement of GH#45333 in 2.0, this remains a view
597
+ np.shares_memory(sliced["C"]._values, float_frame["C"]._values)
598
+ else:
599
+ tm.assert_frame_equal(float_frame, original)
600
+
601
+ def test_getitem_setitem_non_ix_labels(self):
602
+ df = DataFrame(range(20), index=date_range("2020-01-01", periods=20))
603
+
604
+ start, end = df.index[[5, 10]]
605
+
606
+ result = df.loc[start:end]
607
+ result2 = df[start:end]
608
+ expected = df[5:11]
609
+ tm.assert_frame_equal(result, expected)
610
+ tm.assert_frame_equal(result2, expected)
611
+
612
+ result = df.copy()
613
+ result.loc[start:end] = 0
614
+ result2 = df.copy()
615
+ result2[start:end] = 0
616
+ expected = df.copy()
617
+ expected[5:11] = 0
618
+ tm.assert_frame_equal(result, expected)
619
+ tm.assert_frame_equal(result2, expected)
620
+
621
+ def test_ix_multi_take(self):
622
+ df = DataFrame(np.random.default_rng(2).standard_normal((3, 2)))
623
+ rs = df.loc[df.index == 0, :]
624
+ xp = df.reindex([0])
625
+ tm.assert_frame_equal(rs, xp)
626
+
627
+ # GH#1321
628
+ df = DataFrame(np.random.default_rng(2).standard_normal((3, 2)))
629
+ rs = df.loc[df.index == 0, df.columns == 1]
630
+ xp = df.reindex(index=[0], columns=[1])
631
+ tm.assert_frame_equal(rs, xp)
632
+
633
+ def test_getitem_fancy_scalar(self, float_frame):
634
+ f = float_frame
635
+ ix = f.loc
636
+
637
+ # individual value
638
+ for col in f.columns:
639
+ ts = f[col]
640
+ for idx in f.index[::5]:
641
+ assert ix[idx, col] == ts[idx]
642
+
643
+ @td.skip_array_manager_invalid_test # TODO(ArrayManager) rewrite not using .values
644
+ def test_setitem_fancy_scalar(self, float_frame):
645
+ f = float_frame
646
+ expected = float_frame.copy()
647
+ ix = f.loc
648
+
649
+ # individual value
650
+ for j, col in enumerate(f.columns):
651
+ f[col]
652
+ for idx in f.index[::5]:
653
+ i = f.index.get_loc(idx)
654
+ val = np.random.default_rng(2).standard_normal()
655
+ expected.iloc[i, j] = val
656
+
657
+ ix[idx, col] = val
658
+ tm.assert_frame_equal(f, expected)
659
+
660
+ def test_getitem_fancy_boolean(self, float_frame):
661
+ f = float_frame
662
+ ix = f.loc
663
+
664
+ expected = f.reindex(columns=["B", "D"])
665
+ result = ix[:, [False, True, False, True]]
666
+ tm.assert_frame_equal(result, expected)
667
+
668
+ expected = f.reindex(index=f.index[5:10], columns=["B", "D"])
669
+ result = ix[f.index[5:10], [False, True, False, True]]
670
+ tm.assert_frame_equal(result, expected)
671
+
672
+ boolvec = f.index > f.index[7]
673
+ expected = f.reindex(index=f.index[boolvec])
674
+ result = ix[boolvec]
675
+ tm.assert_frame_equal(result, expected)
676
+ result = ix[boolvec, :]
677
+ tm.assert_frame_equal(result, expected)
678
+
679
+ result = ix[boolvec, f.columns[2:]]
680
+ expected = f.reindex(index=f.index[boolvec], columns=["C", "D"])
681
+ tm.assert_frame_equal(result, expected)
682
+
683
+ @td.skip_array_manager_invalid_test # TODO(ArrayManager) rewrite not using .values
684
+ def test_setitem_fancy_boolean(self, float_frame):
685
+ # from 2d, set with booleans
686
+ frame = float_frame.copy()
687
+ expected = float_frame.copy()
688
+ values = expected.values.copy()
689
+
690
+ mask = frame["A"] > 0
691
+ frame.loc[mask] = 0.0
692
+ values[mask.values] = 0.0
693
+ expected = DataFrame(values, index=expected.index, columns=expected.columns)
694
+ tm.assert_frame_equal(frame, expected)
695
+
696
+ frame = float_frame.copy()
697
+ expected = float_frame.copy()
698
+ values = expected.values.copy()
699
+ frame.loc[mask, ["A", "B"]] = 0.0
700
+ values[mask.values, :2] = 0.0
701
+ expected = DataFrame(values, index=expected.index, columns=expected.columns)
702
+ tm.assert_frame_equal(frame, expected)
703
+
704
+ def test_getitem_fancy_ints(self, float_frame):
705
+ result = float_frame.iloc[[1, 4, 7]]
706
+ expected = float_frame.loc[float_frame.index[[1, 4, 7]]]
707
+ tm.assert_frame_equal(result, expected)
708
+
709
+ result = float_frame.iloc[:, [2, 0, 1]]
710
+ expected = float_frame.loc[:, float_frame.columns[[2, 0, 1]]]
711
+ tm.assert_frame_equal(result, expected)
712
+
713
+ def test_getitem_setitem_boolean_misaligned(self, float_frame):
714
+ # boolean index misaligned labels
715
+ mask = float_frame["A"][::-1] > 1
716
+
717
+ result = float_frame.loc[mask]
718
+ expected = float_frame.loc[mask[::-1]]
719
+ tm.assert_frame_equal(result, expected)
720
+
721
+ cp = float_frame.copy()
722
+ expected = float_frame.copy()
723
+ cp.loc[mask] = 0
724
+ expected.loc[mask] = 0
725
+ tm.assert_frame_equal(cp, expected)
726
+
727
+ def test_getitem_setitem_boolean_multi(self):
728
+ df = DataFrame(np.random.default_rng(2).standard_normal((3, 2)))
729
+
730
+ # get
731
+ k1 = np.array([True, False, True])
732
+ k2 = np.array([False, True])
733
+ result = df.loc[k1, k2]
734
+ expected = df.loc[[0, 2], [1]]
735
+ tm.assert_frame_equal(result, expected)
736
+
737
+ expected = df.copy()
738
+ df.loc[np.array([True, False, True]), np.array([False, True])] = 5
739
+ expected.loc[[0, 2], [1]] = 5
740
+ tm.assert_frame_equal(df, expected)
741
+
742
+ def test_getitem_setitem_float_labels(self, using_array_manager):
743
+ index = Index([1.5, 2, 3, 4, 5])
744
+ df = DataFrame(np.random.default_rng(2).standard_normal((5, 5)), index=index)
745
+
746
+ result = df.loc[1.5:4]
747
+ expected = df.reindex([1.5, 2, 3, 4])
748
+ tm.assert_frame_equal(result, expected)
749
+ assert len(result) == 4
750
+
751
+ result = df.loc[4:5]
752
+ expected = df.reindex([4, 5]) # reindex with int
753
+ tm.assert_frame_equal(result, expected, check_index_type=False)
754
+ assert len(result) == 2
755
+
756
+ result = df.loc[4:5]
757
+ expected = df.reindex([4.0, 5.0]) # reindex with float
758
+ tm.assert_frame_equal(result, expected)
759
+ assert len(result) == 2
760
+
761
+ # loc_float changes this to work properly
762
+ result = df.loc[1:2]
763
+ expected = df.iloc[0:2]
764
+ tm.assert_frame_equal(result, expected)
765
+
766
+ expected = df.iloc[0:2]
767
+ msg = r"The behavior of obj\[i:j\] with a float-dtype index"
768
+ with tm.assert_produces_warning(FutureWarning, match=msg):
769
+ result = df[1:2]
770
+ tm.assert_frame_equal(result, expected)
771
+
772
+ # #2727
773
+ index = Index([1.0, 2.5, 3.5, 4.5, 5.0])
774
+ df = DataFrame(np.random.default_rng(2).standard_normal((5, 5)), index=index)
775
+
776
+ # positional slicing only via iloc!
777
+ msg = (
778
+ "cannot do positional indexing on Index with "
779
+ r"these indexers \[1.0\] of type float"
780
+ )
781
+ with pytest.raises(TypeError, match=msg):
782
+ df.iloc[1.0:5]
783
+
784
+ result = df.iloc[4:5]
785
+ expected = df.reindex([5.0])
786
+ tm.assert_frame_equal(result, expected)
787
+ assert len(result) == 1
788
+
789
+ cp = df.copy()
790
+
791
+ with pytest.raises(TypeError, match=_slice_msg):
792
+ cp.iloc[1.0:5] = 0
793
+
794
+ with pytest.raises(TypeError, match=msg):
795
+ result = cp.iloc[1.0:5] == 0
796
+
797
+ assert result.values.all()
798
+ assert (cp.iloc[0:1] == df.iloc[0:1]).values.all()
799
+
800
+ cp = df.copy()
801
+ cp.iloc[4:5] = 0
802
+ assert (cp.iloc[4:5] == 0).values.all()
803
+ assert (cp.iloc[0:4] == df.iloc[0:4]).values.all()
804
+
805
+ # float slicing
806
+ result = df.loc[1.0:5]
807
+ expected = df
808
+ tm.assert_frame_equal(result, expected)
809
+ assert len(result) == 5
810
+
811
+ result = df.loc[1.1:5]
812
+ expected = df.reindex([2.5, 3.5, 4.5, 5.0])
813
+ tm.assert_frame_equal(result, expected)
814
+ assert len(result) == 4
815
+
816
+ result = df.loc[4.51:5]
817
+ expected = df.reindex([5.0])
818
+ tm.assert_frame_equal(result, expected)
819
+ assert len(result) == 1
820
+
821
+ result = df.loc[1.0:5.0]
822
+ expected = df.reindex([1.0, 2.5, 3.5, 4.5, 5.0])
823
+ tm.assert_frame_equal(result, expected)
824
+ assert len(result) == 5
825
+
826
+ cp = df.copy()
827
+ cp.loc[1.0:5.0] = 0
828
+ result = cp.loc[1.0:5.0]
829
+ assert (result == 0).values.all()
830
+
831
+ def test_setitem_single_column_mixed_datetime(self):
832
+ df = DataFrame(
833
+ np.random.default_rng(2).standard_normal((5, 3)),
834
+ index=["a", "b", "c", "d", "e"],
835
+ columns=["foo", "bar", "baz"],
836
+ )
837
+
838
+ df["timestamp"] = Timestamp("20010102")
839
+
840
+ # check our dtypes
841
+ result = df.dtypes
842
+ expected = Series(
843
+ [np.dtype("float64")] * 3 + [np.dtype("datetime64[s]")],
844
+ index=["foo", "bar", "baz", "timestamp"],
845
+ )
846
+ tm.assert_series_equal(result, expected)
847
+
848
+ # GH#16674 iNaT is treated as an integer when given by the user
849
+ with tm.assert_produces_warning(
850
+ FutureWarning, match="Setting an item of incompatible dtype"
851
+ ):
852
+ df.loc["b", "timestamp"] = iNaT
853
+ assert not isna(df.loc["b", "timestamp"])
854
+ assert df["timestamp"].dtype == np.object_
855
+ assert df.loc["b", "timestamp"] == iNaT
856
+
857
+ # allow this syntax (as of GH#3216)
858
+ df.loc["c", "timestamp"] = np.nan
859
+ assert isna(df.loc["c", "timestamp"])
860
+
861
+ # allow this syntax
862
+ df.loc["d", :] = np.nan
863
+ assert not isna(df.loc["c", :]).all()
864
+
865
+ def test_setitem_mixed_datetime(self):
866
+ # GH 9336
867
+ expected = DataFrame(
868
+ {
869
+ "a": [0, 0, 0, 0, 13, 14],
870
+ "b": [
871
+ datetime(2012, 1, 1),
872
+ 1,
873
+ "x",
874
+ "y",
875
+ datetime(2013, 1, 1),
876
+ datetime(2014, 1, 1),
877
+ ],
878
+ }
879
+ )
880
+ df = DataFrame(0, columns=list("ab"), index=range(6))
881
+ df["b"] = pd.NaT
882
+ df.loc[0, "b"] = datetime(2012, 1, 1)
883
+ with tm.assert_produces_warning(
884
+ FutureWarning, match="Setting an item of incompatible dtype"
885
+ ):
886
+ df.loc[1, "b"] = 1
887
+ df.loc[[2, 3], "b"] = "x", "y"
888
+ A = np.array(
889
+ [
890
+ [13, np.datetime64("2013-01-01T00:00:00")],
891
+ [14, np.datetime64("2014-01-01T00:00:00")],
892
+ ]
893
+ )
894
+ df.loc[[4, 5], ["a", "b"]] = A
895
+ tm.assert_frame_equal(df, expected)
896
+
897
+ def test_setitem_frame_float(self, float_frame):
898
+ piece = float_frame.loc[float_frame.index[:2], ["A", "B"]]
899
+ float_frame.loc[float_frame.index[-2] :, ["A", "B"]] = piece.values
900
+ result = float_frame.loc[float_frame.index[-2:], ["A", "B"]].values
901
+ expected = piece.values
902
+ tm.assert_almost_equal(result, expected)
903
+
904
+ def test_setitem_frame_mixed(self, float_string_frame):
905
+ # GH 3216
906
+
907
+ # already aligned
908
+ f = float_string_frame.copy()
909
+ piece = DataFrame(
910
+ [[1.0, 2.0], [3.0, 4.0]], index=f.index[0:2], columns=["A", "B"]
911
+ )
912
+ key = (f.index[slice(None, 2)], ["A", "B"])
913
+ f.loc[key] = piece
914
+ tm.assert_almost_equal(f.loc[f.index[0:2], ["A", "B"]].values, piece.values)
915
+
916
+ def test_setitem_frame_mixed_rows_unaligned(self, float_string_frame):
917
+ # GH#3216 rows unaligned
918
+ f = float_string_frame.copy()
919
+ piece = DataFrame(
920
+ [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]],
921
+ index=list(f.index[0:2]) + ["foo", "bar"],
922
+ columns=["A", "B"],
923
+ )
924
+ key = (f.index[slice(None, 2)], ["A", "B"])
925
+ f.loc[key] = piece
926
+ tm.assert_almost_equal(
927
+ f.loc[f.index[0:2:], ["A", "B"]].values, piece.values[0:2]
928
+ )
929
+
930
+ def test_setitem_frame_mixed_key_unaligned(self, float_string_frame):
931
+ # GH#3216 key is unaligned with values
932
+ f = float_string_frame.copy()
933
+ piece = f.loc[f.index[:2], ["A"]]
934
+ piece.index = f.index[-2:]
935
+ key = (f.index[slice(-2, None)], ["A", "B"])
936
+ f.loc[key] = piece
937
+ piece["B"] = np.nan
938
+ tm.assert_almost_equal(f.loc[f.index[-2:], ["A", "B"]].values, piece.values)
939
+
940
+ def test_setitem_frame_mixed_ndarray(self, float_string_frame):
941
+ # GH#3216 ndarray
942
+ f = float_string_frame.copy()
943
+ piece = float_string_frame.loc[f.index[:2], ["A", "B"]]
944
+ key = (f.index[slice(-2, None)], ["A", "B"])
945
+ f.loc[key] = piece.values
946
+ tm.assert_almost_equal(f.loc[f.index[-2:], ["A", "B"]].values, piece.values)
947
+
948
+ def test_setitem_frame_upcast(self):
949
+ # needs upcasting
950
+ df = DataFrame([[1, 2, "foo"], [3, 4, "bar"]], columns=["A", "B", "C"])
951
+ df2 = df.copy()
952
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
953
+ df2.loc[:, ["A", "B"]] = df.loc[:, ["A", "B"]] + 0.5
954
+ expected = df.reindex(columns=["A", "B"])
955
+ expected += 0.5
956
+ expected["C"] = df["C"]
957
+ tm.assert_frame_equal(df2, expected)
958
+
959
+ def test_setitem_frame_align(self, float_frame):
960
+ piece = float_frame.loc[float_frame.index[:2], ["A", "B"]]
961
+ piece.index = float_frame.index[-2:]
962
+ piece.columns = ["A", "B"]
963
+ float_frame.loc[float_frame.index[-2:], ["A", "B"]] = piece
964
+ result = float_frame.loc[float_frame.index[-2:], ["A", "B"]].values
965
+ expected = piece.values
966
+ tm.assert_almost_equal(result, expected)
967
+
968
+ def test_getitem_setitem_ix_duplicates(self):
969
+ # #1201
970
+ df = DataFrame(
971
+ np.random.default_rng(2).standard_normal((5, 3)),
972
+ index=["foo", "foo", "bar", "baz", "bar"],
973
+ )
974
+
975
+ result = df.loc["foo"]
976
+ expected = df[:2]
977
+ tm.assert_frame_equal(result, expected)
978
+
979
+ result = df.loc["bar"]
980
+ expected = df.iloc[[2, 4]]
981
+ tm.assert_frame_equal(result, expected)
982
+
983
+ result = df.loc["baz"]
984
+ expected = df.iloc[3]
985
+ tm.assert_series_equal(result, expected)
986
+
987
+ def test_getitem_ix_boolean_duplicates_multiple(self):
988
+ # #1201
989
+ df = DataFrame(
990
+ np.random.default_rng(2).standard_normal((5, 3)),
991
+ index=["foo", "foo", "bar", "baz", "bar"],
992
+ )
993
+
994
+ result = df.loc[["bar"]]
995
+ exp = df.iloc[[2, 4]]
996
+ tm.assert_frame_equal(result, exp)
997
+
998
+ result = df.loc[df[1] > 0]
999
+ exp = df[df[1] > 0]
1000
+ tm.assert_frame_equal(result, exp)
1001
+
1002
+ result = df.loc[df[0] > 0]
1003
+ exp = df[df[0] > 0]
1004
+ tm.assert_frame_equal(result, exp)
1005
+
1006
+ @pytest.mark.parametrize("bool_value", [True, False])
1007
+ def test_getitem_setitem_ix_bool_keyerror(self, bool_value):
1008
+ # #2199
1009
+ df = DataFrame({"a": [1, 2, 3]})
1010
+ message = f"{bool_value}: boolean label can not be used without a boolean index"
1011
+ with pytest.raises(KeyError, match=message):
1012
+ df.loc[bool_value]
1013
+
1014
+ msg = "cannot use a single bool to index into setitem"
1015
+ with pytest.raises(KeyError, match=msg):
1016
+ df.loc[bool_value] = 0
1017
+
1018
+ # TODO: rename? remove?
1019
+ def test_single_element_ix_dont_upcast(self, float_frame):
1020
+ float_frame["E"] = 1
1021
+ assert issubclass(float_frame["E"].dtype.type, (int, np.integer))
1022
+
1023
+ result = float_frame.loc[float_frame.index[5], "E"]
1024
+ assert is_integer(result)
1025
+
1026
+ # GH 11617
1027
+ df = DataFrame({"a": [1.23]})
1028
+ df["b"] = 666
1029
+
1030
+ result = df.loc[0, "b"]
1031
+ assert is_integer(result)
1032
+
1033
+ expected = Series([666], [0], name="b")
1034
+ result = df.loc[[0], "b"]
1035
+ tm.assert_series_equal(result, expected)
1036
+
1037
+ def test_iloc_callable_tuple_return_value(self):
1038
+ # GH53769
1039
+ df = DataFrame(np.arange(40).reshape(10, 4), index=range(0, 20, 2))
1040
+ msg = "callable with iloc"
1041
+ with tm.assert_produces_warning(FutureWarning, match=msg):
1042
+ df.iloc[lambda _: (0,)]
1043
+ with tm.assert_produces_warning(FutureWarning, match=msg):
1044
+ df.iloc[lambda _: (0,)] = 1
1045
+
1046
+ def test_iloc_row(self):
1047
+ df = DataFrame(
1048
+ np.random.default_rng(2).standard_normal((10, 4)), index=range(0, 20, 2)
1049
+ )
1050
+
1051
+ result = df.iloc[1]
1052
+ exp = df.loc[2]
1053
+ tm.assert_series_equal(result, exp)
1054
+
1055
+ result = df.iloc[2]
1056
+ exp = df.loc[4]
1057
+ tm.assert_series_equal(result, exp)
1058
+
1059
+ # slice
1060
+ result = df.iloc[slice(4, 8)]
1061
+ expected = df.loc[8:14]
1062
+ tm.assert_frame_equal(result, expected)
1063
+
1064
+ # list of integers
1065
+ result = df.iloc[[1, 2, 4, 6]]
1066
+ expected = df.reindex(df.index[[1, 2, 4, 6]])
1067
+ tm.assert_frame_equal(result, expected)
1068
+
1069
+ def test_iloc_row_slice_view(self, using_copy_on_write, warn_copy_on_write):
1070
+ df = DataFrame(
1071
+ np.random.default_rng(2).standard_normal((10, 4)), index=range(0, 20, 2)
1072
+ )
1073
+ original = df.copy()
1074
+
1075
+ # verify slice is view
1076
+ # setting it makes it raise/warn
1077
+ subset = df.iloc[slice(4, 8)]
1078
+
1079
+ assert np.shares_memory(df[2], subset[2])
1080
+
1081
+ exp_col = original[2].copy()
1082
+ with tm.assert_cow_warning(warn_copy_on_write):
1083
+ subset.loc[:, 2] = 0.0
1084
+ if not using_copy_on_write:
1085
+ exp_col._values[4:8] = 0.0
1086
+
1087
+ # With the enforcement of GH#45333 in 2.0, this remains a view
1088
+ assert np.shares_memory(df[2], subset[2])
1089
+ tm.assert_series_equal(df[2], exp_col)
1090
+
1091
+ def test_iloc_col(self):
1092
+ df = DataFrame(
1093
+ np.random.default_rng(2).standard_normal((4, 10)), columns=range(0, 20, 2)
1094
+ )
1095
+
1096
+ result = df.iloc[:, 1]
1097
+ exp = df.loc[:, 2]
1098
+ tm.assert_series_equal(result, exp)
1099
+
1100
+ result = df.iloc[:, 2]
1101
+ exp = df.loc[:, 4]
1102
+ tm.assert_series_equal(result, exp)
1103
+
1104
+ # slice
1105
+ result = df.iloc[:, slice(4, 8)]
1106
+ expected = df.loc[:, 8:14]
1107
+ tm.assert_frame_equal(result, expected)
1108
+
1109
+ # list of integers
1110
+ result = df.iloc[:, [1, 2, 4, 6]]
1111
+ expected = df.reindex(columns=df.columns[[1, 2, 4, 6]])
1112
+ tm.assert_frame_equal(result, expected)
1113
+
1114
+ def test_iloc_col_slice_view(
1115
+ self, using_array_manager, using_copy_on_write, warn_copy_on_write
1116
+ ):
1117
+ df = DataFrame(
1118
+ np.random.default_rng(2).standard_normal((4, 10)), columns=range(0, 20, 2)
1119
+ )
1120
+ original = df.copy()
1121
+ subset = df.iloc[:, slice(4, 8)]
1122
+
1123
+ if not using_array_manager and not using_copy_on_write:
1124
+ # verify slice is view
1125
+ assert np.shares_memory(df[8]._values, subset[8]._values)
1126
+
1127
+ with tm.assert_cow_warning(warn_copy_on_write):
1128
+ subset.loc[:, 8] = 0.0
1129
+
1130
+ assert (df[8] == 0).all()
1131
+
1132
+ # with the enforcement of GH#45333 in 2.0, this remains a view
1133
+ assert np.shares_memory(df[8]._values, subset[8]._values)
1134
+ else:
1135
+ if using_copy_on_write:
1136
+ # verify slice is view
1137
+ assert np.shares_memory(df[8]._values, subset[8]._values)
1138
+ subset[8] = 0.0
1139
+ # subset changed
1140
+ assert (subset[8] == 0).all()
1141
+ # but df itself did not change (setitem replaces full column)
1142
+ tm.assert_frame_equal(df, original)
1143
+
1144
+ def test_loc_duplicates(self):
1145
+ # gh-17105
1146
+
1147
+ # insert a duplicate element to the index
1148
+ trange = date_range(
1149
+ start=Timestamp(year=2017, month=1, day=1),
1150
+ end=Timestamp(year=2017, month=1, day=5),
1151
+ )
1152
+
1153
+ trange = trange.insert(loc=5, item=Timestamp(year=2017, month=1, day=5))
1154
+
1155
+ df = DataFrame(0, index=trange, columns=["A", "B"])
1156
+ bool_idx = np.array([False, False, False, False, False, True])
1157
+
1158
+ # assignment
1159
+ df.loc[trange[bool_idx], "A"] = 6
1160
+
1161
+ expected = DataFrame(
1162
+ {"A": [0, 0, 0, 0, 6, 6], "B": [0, 0, 0, 0, 0, 0]}, index=trange
1163
+ )
1164
+ tm.assert_frame_equal(df, expected)
1165
+
1166
+ # in-place
1167
+ df = DataFrame(0, index=trange, columns=["A", "B"])
1168
+ df.loc[trange[bool_idx], "A"] += 6
1169
+ tm.assert_frame_equal(df, expected)
1170
+
1171
+ def test_setitem_with_unaligned_tz_aware_datetime_column(self):
1172
+ # GH 12981
1173
+ # Assignment of unaligned offset-aware datetime series.
1174
+ # Make sure timezone isn't lost
1175
+ column = Series(date_range("2015-01-01", periods=3, tz="utc"), name="dates")
1176
+ df = DataFrame({"dates": column})
1177
+ df["dates"] = column[[1, 0, 2]]
1178
+ tm.assert_series_equal(df["dates"], column)
1179
+
1180
+ df = DataFrame({"dates": column})
1181
+ df.loc[[0, 1, 2], "dates"] = column[[1, 0, 2]]
1182
+ tm.assert_series_equal(df["dates"], column)
1183
+
1184
+ def test_loc_setitem_datetimelike_with_inference(self):
1185
+ # GH 7592
1186
+ # assignment of timedeltas with NaT
1187
+
1188
+ one_hour = timedelta(hours=1)
1189
+ df = DataFrame(index=date_range("20130101", periods=4))
1190
+ df["A"] = np.array([1 * one_hour] * 4, dtype="m8[ns]")
1191
+ df.loc[:, "B"] = np.array([2 * one_hour] * 4, dtype="m8[ns]")
1192
+ df.loc[df.index[:3], "C"] = np.array([3 * one_hour] * 3, dtype="m8[ns]")
1193
+ df.loc[:, "D"] = np.array([4 * one_hour] * 4, dtype="m8[ns]")
1194
+ df.loc[df.index[:3], "E"] = np.array([5 * one_hour] * 3, dtype="m8[ns]")
1195
+ df["F"] = np.timedelta64("NaT")
1196
+ df.loc[df.index[:-1], "F"] = np.array([6 * one_hour] * 3, dtype="m8[ns]")
1197
+ df.loc[df.index[-3] :, "G"] = date_range("20130101", periods=3)
1198
+ df["H"] = np.datetime64("NaT")
1199
+ result = df.dtypes
1200
+ expected = Series(
1201
+ [np.dtype("timedelta64[ns]")] * 6 + [np.dtype("datetime64[ns]")] * 2,
1202
+ index=list("ABCDEFGH"),
1203
+ )
1204
+ tm.assert_series_equal(result, expected)
1205
+
1206
+ def test_getitem_boolean_indexing_mixed(self):
1207
+ df = DataFrame(
1208
+ {
1209
+ 0: {35: np.nan, 40: np.nan, 43: np.nan, 49: np.nan, 50: np.nan},
1210
+ 1: {
1211
+ 35: np.nan,
1212
+ 40: 0.32632316859446198,
1213
+ 43: np.nan,
1214
+ 49: 0.32632316859446198,
1215
+ 50: 0.39114724480578139,
1216
+ },
1217
+ 2: {
1218
+ 35: np.nan,
1219
+ 40: np.nan,
1220
+ 43: 0.29012581014105987,
1221
+ 49: np.nan,
1222
+ 50: np.nan,
1223
+ },
1224
+ 3: {35: np.nan, 40: np.nan, 43: np.nan, 49: np.nan, 50: np.nan},
1225
+ 4: {
1226
+ 35: 0.34215328467153283,
1227
+ 40: np.nan,
1228
+ 43: np.nan,
1229
+ 49: np.nan,
1230
+ 50: np.nan,
1231
+ },
1232
+ "y": {35: 0, 40: 0, 43: 0, 49: 0, 50: 1},
1233
+ }
1234
+ )
1235
+
1236
+ # mixed int/float ok
1237
+ df2 = df.copy()
1238
+ df2[df2 > 0.3] = 1
1239
+ expected = df.copy()
1240
+ expected.loc[40, 1] = 1
1241
+ expected.loc[49, 1] = 1
1242
+ expected.loc[50, 1] = 1
1243
+ expected.loc[35, 4] = 1
1244
+ tm.assert_frame_equal(df2, expected)
1245
+
1246
+ df["foo"] = "test"
1247
+ msg = "not supported between instances|unorderable types"
1248
+
1249
+ with pytest.raises(TypeError, match=msg):
1250
+ df[df > 0.3] = 1
1251
+
1252
+ def test_type_error_multiindex(self):
1253
+ # See gh-12218
1254
+ mi = MultiIndex.from_product([["x", "y"], [0, 1]], names=[None, "c"])
1255
+ dg = DataFrame(
1256
+ [[1, 1, 2, 2], [3, 3, 4, 4]], columns=mi, index=Index([0, 1], name="i")
1257
+ )
1258
+ with pytest.raises(InvalidIndexError, match="slice"):
1259
+ dg[:, 0]
1260
+
1261
+ index = Index(range(2), name="i")
1262
+ columns = MultiIndex(
1263
+ levels=[["x", "y"], [0, 1]], codes=[[0, 1], [0, 0]], names=[None, "c"]
1264
+ )
1265
+ expected = DataFrame([[1, 2], [3, 4]], columns=columns, index=index)
1266
+
1267
+ result = dg.loc[:, (slice(None), 0)]
1268
+ tm.assert_frame_equal(result, expected)
1269
+
1270
+ name = ("x", 0)
1271
+ index = Index(range(2), name="i")
1272
+ expected = Series([1, 3], index=index, name=name)
1273
+
1274
+ result = dg["x", 0]
1275
+ tm.assert_series_equal(result, expected)
1276
+
1277
+ def test_getitem_interval_index_partial_indexing(self):
1278
+ # GH#36490
1279
+ df = DataFrame(
1280
+ np.ones((3, 4)), columns=pd.IntervalIndex.from_breaks(np.arange(5))
1281
+ )
1282
+
1283
+ expected = df.iloc[:, 0]
1284
+
1285
+ res = df[0.5]
1286
+ tm.assert_series_equal(res, expected)
1287
+
1288
+ res = df.loc[:, 0.5]
1289
+ tm.assert_series_equal(res, expected)
1290
+
1291
+ def test_setitem_array_as_cell_value(self):
1292
+ # GH#43422
1293
+ df = DataFrame(columns=["a", "b"], dtype=object)
1294
+ df.loc[0] = {"a": np.zeros((2,)), "b": np.zeros((2, 2))}
1295
+ expected = DataFrame({"a": [np.zeros((2,))], "b": [np.zeros((2, 2))]})
1296
+ tm.assert_frame_equal(df, expected)
1297
+
1298
+ def test_iloc_setitem_nullable_2d_values(self):
1299
+ df = DataFrame({"A": [1, 2, 3]}, dtype="Int64")
1300
+ orig = df.copy()
1301
+
1302
+ df.loc[:] = df.values[:, ::-1]
1303
+ tm.assert_frame_equal(df, orig)
1304
+
1305
+ df.loc[:] = pd.core.arrays.NumpyExtensionArray(df.values[:, ::-1])
1306
+ tm.assert_frame_equal(df, orig)
1307
+
1308
+ df.iloc[:] = df.iloc[:, :].copy()
1309
+ tm.assert_frame_equal(df, orig)
1310
+
1311
+ def test_getitem_segfault_with_empty_like_object(self):
1312
+ # GH#46848
1313
+ df = DataFrame(np.empty((1, 1), dtype=object))
1314
+ df[0] = np.empty_like(df[0])
1315
+ # this produces the segfault
1316
+ df[[0]]
1317
+
1318
+ @pytest.mark.filterwarnings("ignore:Setting a value on a view:FutureWarning")
1319
+ @pytest.mark.parametrize(
1320
+ "null", [pd.NaT, pd.NaT.to_numpy("M8[ns]"), pd.NaT.to_numpy("m8[ns]")]
1321
+ )
1322
+ def test_setting_mismatched_na_into_nullable_fails(
1323
+ self, null, any_numeric_ea_dtype
1324
+ ):
1325
+ # GH#44514 don't cast mismatched nulls to pd.NA
1326
+ df = DataFrame({"A": [1, 2, 3]}, dtype=any_numeric_ea_dtype)
1327
+ ser = df["A"].copy()
1328
+ arr = ser._values
1329
+
1330
+ msg = "|".join(
1331
+ [
1332
+ r"timedelta64\[ns\] cannot be converted to (Floating|Integer)Dtype",
1333
+ r"datetime64\[ns\] cannot be converted to (Floating|Integer)Dtype",
1334
+ "'values' contains non-numeric NA",
1335
+ r"Invalid value '.*' for dtype (U?Int|Float)\d{1,2}",
1336
+ ]
1337
+ )
1338
+ with pytest.raises(TypeError, match=msg):
1339
+ arr[0] = null
1340
+
1341
+ with pytest.raises(TypeError, match=msg):
1342
+ arr[:2] = [null, null]
1343
+
1344
+ with pytest.raises(TypeError, match=msg):
1345
+ ser[0] = null
1346
+
1347
+ with pytest.raises(TypeError, match=msg):
1348
+ ser[:2] = [null, null]
1349
+
1350
+ with pytest.raises(TypeError, match=msg):
1351
+ ser.iloc[0] = null
1352
+
1353
+ with pytest.raises(TypeError, match=msg):
1354
+ ser.iloc[:2] = [null, null]
1355
+
1356
+ with pytest.raises(TypeError, match=msg):
1357
+ df.iloc[0, 0] = null
1358
+
1359
+ with pytest.raises(TypeError, match=msg):
1360
+ df.iloc[:2, 0] = [null, null]
1361
+
1362
+ # Multi-Block
1363
+ df2 = df.copy()
1364
+ df2["B"] = ser.copy()
1365
+ with pytest.raises(TypeError, match=msg):
1366
+ df2.iloc[0, 0] = null
1367
+
1368
+ with pytest.raises(TypeError, match=msg):
1369
+ df2.iloc[:2, 0] = [null, null]
1370
+
1371
+ def test_loc_expand_empty_frame_keep_index_name(self):
1372
+ # GH#45621
1373
+ df = DataFrame(columns=["b"], index=Index([], name="a"))
1374
+ df.loc[0] = 1
1375
+ expected = DataFrame({"b": [1]}, index=Index([0], name="a"))
1376
+ tm.assert_frame_equal(df, expected)
1377
+
1378
+ def test_loc_expand_empty_frame_keep_midx_names(self):
1379
+ # GH#46317
1380
+ df = DataFrame(
1381
+ columns=["d"], index=MultiIndex.from_tuples([], names=["a", "b", "c"])
1382
+ )
1383
+ df.loc[(1, 2, 3)] = "foo"
1384
+ expected = DataFrame(
1385
+ {"d": ["foo"]},
1386
+ index=MultiIndex.from_tuples([(1, 2, 3)], names=["a", "b", "c"]),
1387
+ )
1388
+ tm.assert_frame_equal(df, expected)
1389
+
1390
+ @pytest.mark.parametrize(
1391
+ "val, idxr",
1392
+ [
1393
+ ("x", "a"),
1394
+ ("x", ["a"]),
1395
+ (1, "a"),
1396
+ (1, ["a"]),
1397
+ ],
1398
+ )
1399
+ def test_loc_setitem_rhs_frame(self, idxr, val):
1400
+ # GH#47578
1401
+ df = DataFrame({"a": [1, 2]})
1402
+
1403
+ with tm.assert_produces_warning(
1404
+ FutureWarning, match="Setting an item of incompatible dtype"
1405
+ ):
1406
+ df.loc[:, idxr] = DataFrame({"a": [val, 11]}, index=[1, 2])
1407
+ expected = DataFrame({"a": [np.nan, val]})
1408
+ tm.assert_frame_equal(df, expected)
1409
+
1410
+ @td.skip_array_manager_invalid_test
1411
+ def test_iloc_setitem_enlarge_no_warning(self, warn_copy_on_write):
1412
+ # GH#47381
1413
+ df = DataFrame(columns=["a", "b"])
1414
+ expected = df.copy()
1415
+ view = df[:]
1416
+ df.iloc[:, 0] = np.array([1, 2], dtype=np.float64)
1417
+ tm.assert_frame_equal(view, expected)
1418
+
1419
+ def test_loc_internals_not_updated_correctly(self):
1420
+ # GH#47867 all steps are necessary to reproduce the initial bug
1421
+ df = DataFrame(
1422
+ {"bool_col": True, "a": 1, "b": 2.5},
1423
+ index=MultiIndex.from_arrays([[1, 2], [1, 2]], names=["idx1", "idx2"]),
1424
+ )
1425
+ idx = [(1, 1)]
1426
+
1427
+ df["c"] = 3
1428
+ df.loc[idx, "c"] = 0
1429
+
1430
+ df.loc[idx, "c"]
1431
+ df.loc[idx, ["a", "b"]]
1432
+
1433
+ df.loc[idx, "c"] = 15
1434
+ result = df.loc[idx, "c"]
1435
+ expected = df = Series(
1436
+ 15,
1437
+ index=MultiIndex.from_arrays([[1], [1]], names=["idx1", "idx2"]),
1438
+ name="c",
1439
+ )
1440
+ tm.assert_series_equal(result, expected)
1441
+
1442
+ @pytest.mark.parametrize("val", [None, [None], pd.NA, [pd.NA]])
1443
+ def test_iloc_setitem_string_list_na(self, val):
1444
+ # GH#45469
1445
+ df = DataFrame({"a": ["a", "b", "c"]}, dtype="string")
1446
+ df.iloc[[0], :] = val
1447
+ expected = DataFrame({"a": [pd.NA, "b", "c"]}, dtype="string")
1448
+ tm.assert_frame_equal(df, expected)
1449
+
1450
+ @pytest.mark.parametrize("val", [None, pd.NA])
1451
+ def test_iloc_setitem_string_na(self, val):
1452
+ # GH#45469
1453
+ df = DataFrame({"a": ["a", "b", "c"]}, dtype="string")
1454
+ df.iloc[0, :] = val
1455
+ expected = DataFrame({"a": [pd.NA, "b", "c"]}, dtype="string")
1456
+ tm.assert_frame_equal(df, expected)
1457
+
1458
+ @pytest.mark.parametrize("func", [list, Series, np.array])
1459
+ def test_iloc_setitem_ea_null_slice_length_one_list(self, func):
1460
+ # GH#48016
1461
+ df = DataFrame({"a": [1, 2, 3]}, dtype="Int64")
1462
+ df.iloc[:, func([0])] = 5
1463
+ expected = DataFrame({"a": [5, 5, 5]}, dtype="Int64")
1464
+ tm.assert_frame_equal(df, expected)
1465
+
1466
+ def test_loc_named_tuple_for_midx(self):
1467
+ # GH#48124
1468
+ df = DataFrame(
1469
+ index=MultiIndex.from_product(
1470
+ [["A", "B"], ["a", "b", "c"]], names=["first", "second"]
1471
+ )
1472
+ )
1473
+ indexer_tuple = namedtuple("Indexer", df.index.names)
1474
+ idxr = indexer_tuple(first="A", second=["a", "b"])
1475
+ result = df.loc[idxr, :]
1476
+ expected = DataFrame(
1477
+ index=MultiIndex.from_tuples(
1478
+ [("A", "a"), ("A", "b")], names=["first", "second"]
1479
+ )
1480
+ )
1481
+ tm.assert_frame_equal(result, expected)
1482
+
1483
+ @pytest.mark.parametrize("indexer", [["a"], "a"])
1484
+ @pytest.mark.parametrize("col", [{}, {"b": 1}])
1485
+ def test_set_2d_casting_date_to_int(self, col, indexer):
1486
+ # GH#49159
1487
+ df = DataFrame(
1488
+ {"a": [Timestamp("2022-12-29"), Timestamp("2022-12-30")], **col},
1489
+ )
1490
+ df.loc[[1], indexer] = df["a"] + pd.Timedelta(days=1)
1491
+ expected = DataFrame(
1492
+ {"a": [Timestamp("2022-12-29"), Timestamp("2022-12-31")], **col},
1493
+ )
1494
+ tm.assert_frame_equal(df, expected)
1495
+
1496
+ @pytest.mark.parametrize("col", [{}, {"name": "a"}])
1497
+ def test_loc_setitem_reordering_with_all_true_indexer(self, col):
1498
+ # GH#48701
1499
+ n = 17
1500
+ df = DataFrame({**col, "x": range(n), "y": range(n)})
1501
+ expected = df.copy()
1502
+ df.loc[n * [True], ["x", "y"]] = df[["x", "y"]]
1503
+ tm.assert_frame_equal(df, expected)
1504
+
1505
+ def test_loc_rhs_empty_warning(self):
1506
+ # GH48480
1507
+ df = DataFrame(columns=["a", "b"])
1508
+ expected = df.copy()
1509
+ rhs = DataFrame(columns=["a"])
1510
+ with tm.assert_produces_warning(None):
1511
+ df.loc[:, "a"] = rhs
1512
+ tm.assert_frame_equal(df, expected)
1513
+
1514
+ def test_iloc_ea_series_indexer(self):
1515
+ # GH#49521
1516
+ df = DataFrame([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
1517
+ indexer = Series([0, 1], dtype="Int64")
1518
+ row_indexer = Series([1], dtype="Int64")
1519
+ result = df.iloc[row_indexer, indexer]
1520
+ expected = DataFrame([[5, 6]], index=[1])
1521
+ tm.assert_frame_equal(result, expected)
1522
+
1523
+ result = df.iloc[row_indexer.values, indexer.values]
1524
+ tm.assert_frame_equal(result, expected)
1525
+
1526
+ def test_iloc_ea_series_indexer_with_na(self):
1527
+ # GH#49521
1528
+ df = DataFrame([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
1529
+ indexer = Series([0, pd.NA], dtype="Int64")
1530
+ msg = "cannot convert"
1531
+ with pytest.raises(ValueError, match=msg):
1532
+ df.iloc[:, indexer]
1533
+ with pytest.raises(ValueError, match=msg):
1534
+ df.iloc[:, indexer.values]
1535
+
1536
+ @pytest.mark.parametrize("indexer", [True, (True,)])
1537
+ @pytest.mark.parametrize("dtype", [bool, "boolean"])
1538
+ def test_loc_bool_multiindex(self, dtype, indexer):
1539
+ # GH#47687
1540
+ midx = MultiIndex.from_arrays(
1541
+ [
1542
+ Series([True, True, False, False], dtype=dtype),
1543
+ Series([True, False, True, False], dtype=dtype),
1544
+ ],
1545
+ names=["a", "b"],
1546
+ )
1547
+ df = DataFrame({"c": [1, 2, 3, 4]}, index=midx)
1548
+ with tm.maybe_produces_warning(PerformanceWarning, isinstance(indexer, tuple)):
1549
+ result = df.loc[indexer]
1550
+ expected = DataFrame(
1551
+ {"c": [1, 2]}, index=Index([True, False], name="b", dtype=dtype)
1552
+ )
1553
+ tm.assert_frame_equal(result, expected)
1554
+
1555
+ @pytest.mark.parametrize("utc", [False, True])
1556
+ @pytest.mark.parametrize("indexer", ["date", ["date"]])
1557
+ def test_loc_datetime_assignment_dtype_does_not_change(self, utc, indexer):
1558
+ # GH#49837
1559
+ df = DataFrame(
1560
+ {
1561
+ "date": to_datetime(
1562
+ [datetime(2022, 1, 20), datetime(2022, 1, 22)], utc=utc
1563
+ ),
1564
+ "update": [True, False],
1565
+ }
1566
+ )
1567
+ expected = df.copy(deep=True)
1568
+
1569
+ update_df = df[df["update"]]
1570
+
1571
+ df.loc[df["update"], indexer] = update_df["date"]
1572
+
1573
+ tm.assert_frame_equal(df, expected)
1574
+
1575
+ @pytest.mark.parametrize("indexer, idx", [(tm.loc, 1), (tm.iloc, 2)])
1576
+ def test_setitem_value_coercing_dtypes(self, indexer, idx):
1577
+ # GH#50467
1578
+ df = DataFrame([["1", np.nan], ["2", np.nan], ["3", np.nan]], dtype=object)
1579
+ rhs = DataFrame([[1, np.nan], [2, np.nan]])
1580
+ indexer(df)[:idx, :] = rhs
1581
+ expected = DataFrame([[1, np.nan], [2, np.nan], ["3", np.nan]], dtype=object)
1582
+ tm.assert_frame_equal(df, expected)
1583
+
1584
+
1585
+ class TestDataFrameIndexingUInt64:
1586
+ def test_setitem(self):
1587
+ df = DataFrame(
1588
+ {"A": np.arange(3), "B": [2**63, 2**63 + 5, 2**63 + 10]},
1589
+ dtype=np.uint64,
1590
+ )
1591
+ idx = df["A"].rename("foo")
1592
+
1593
+ # setitem
1594
+ assert "C" not in df.columns
1595
+ df["C"] = idx
1596
+ tm.assert_series_equal(df["C"], Series(idx, name="C"))
1597
+
1598
+ assert "D" not in df.columns
1599
+ df["D"] = "foo"
1600
+ df["D"] = idx
1601
+ tm.assert_series_equal(df["D"], Series(idx, name="D"))
1602
+ del df["D"]
1603
+
1604
+ # With NaN: because uint64 has no NaN element,
1605
+ # the column should be cast to object.
1606
+ df2 = df.copy()
1607
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
1608
+ df2.iloc[1, 1] = pd.NaT
1609
+ df2.iloc[1, 2] = pd.NaT
1610
+ result = df2["B"]
1611
+ tm.assert_series_equal(notna(result), Series([True, False, True], name="B"))
1612
+ tm.assert_series_equal(
1613
+ df2.dtypes,
1614
+ Series(
1615
+ [np.dtype("uint64"), np.dtype("O"), np.dtype("O")],
1616
+ index=["A", "B", "C"],
1617
+ ),
1618
+ )
1619
+
1620
+
1621
+ def test_object_casting_indexing_wraps_datetimelike(using_array_manager):
1622
+ # GH#31649, check the indexing methods all the way down the stack
1623
+ df = DataFrame(
1624
+ {
1625
+ "A": [1, 2],
1626
+ "B": date_range("2000", periods=2),
1627
+ "C": pd.timedelta_range("1 Day", periods=2),
1628
+ }
1629
+ )
1630
+
1631
+ ser = df.loc[0]
1632
+ assert isinstance(ser.values[1], Timestamp)
1633
+ assert isinstance(ser.values[2], pd.Timedelta)
1634
+
1635
+ ser = df.iloc[0]
1636
+ assert isinstance(ser.values[1], Timestamp)
1637
+ assert isinstance(ser.values[2], pd.Timedelta)
1638
+
1639
+ ser = df.xs(0, axis=0)
1640
+ assert isinstance(ser.values[1], Timestamp)
1641
+ assert isinstance(ser.values[2], pd.Timedelta)
1642
+
1643
+ if using_array_manager:
1644
+ # remainder of the test checking BlockManager internals
1645
+ return
1646
+
1647
+ mgr = df._mgr
1648
+ mgr._rebuild_blknos_and_blklocs()
1649
+ arr = mgr.fast_xs(0).array
1650
+ assert isinstance(arr[1], Timestamp)
1651
+ assert isinstance(arr[2], pd.Timedelta)
1652
+
1653
+ blk = mgr.blocks[mgr.blknos[1]]
1654
+ assert blk.dtype == "M8[ns]" # we got the right block
1655
+ val = blk.iget((0, 0))
1656
+ assert isinstance(val, Timestamp)
1657
+
1658
+ blk = mgr.blocks[mgr.blknos[2]]
1659
+ assert blk.dtype == "m8[ns]" # we got the right block
1660
+ val = blk.iget((0, 0))
1661
+ assert isinstance(val, pd.Timedelta)
1662
+
1663
+
1664
+ msg1 = r"Cannot setitem on a Categorical with a new category( \(.*\))?, set the"
1665
+ msg2 = "Cannot set a Categorical with another, without identical categories"
1666
+
1667
+
1668
+ class TestLocILocDataFrameCategorical:
1669
+ @pytest.fixture
1670
+ def orig(self):
1671
+ cats = Categorical(["a", "a", "a", "a", "a", "a", "a"], categories=["a", "b"])
1672
+ idx = Index(["h", "i", "j", "k", "l", "m", "n"])
1673
+ values = [1, 1, 1, 1, 1, 1, 1]
1674
+ orig = DataFrame({"cats": cats, "values": values}, index=idx)
1675
+ return orig
1676
+
1677
+ @pytest.fixture
1678
+ def exp_single_row(self):
1679
+ # The expected values if we change a single row
1680
+ cats1 = Categorical(["a", "a", "b", "a", "a", "a", "a"], categories=["a", "b"])
1681
+ idx1 = Index(["h", "i", "j", "k", "l", "m", "n"])
1682
+ values1 = [1, 1, 2, 1, 1, 1, 1]
1683
+ exp_single_row = DataFrame({"cats": cats1, "values": values1}, index=idx1)
1684
+ return exp_single_row
1685
+
1686
+ @pytest.fixture
1687
+ def exp_multi_row(self):
1688
+ # assign multiple rows (mixed values) (-> array) -> exp_multi_row
1689
+ # changed multiple rows
1690
+ cats2 = Categorical(["a", "a", "b", "b", "a", "a", "a"], categories=["a", "b"])
1691
+ idx2 = Index(["h", "i", "j", "k", "l", "m", "n"])
1692
+ values2 = [1, 1, 2, 2, 1, 1, 1]
1693
+ exp_multi_row = DataFrame({"cats": cats2, "values": values2}, index=idx2)
1694
+ return exp_multi_row
1695
+
1696
+ @pytest.fixture
1697
+ def exp_parts_cats_col(self):
1698
+ # changed part of the cats column
1699
+ cats3 = Categorical(["a", "a", "b", "b", "a", "a", "a"], categories=["a", "b"])
1700
+ idx3 = Index(["h", "i", "j", "k", "l", "m", "n"])
1701
+ values3 = [1, 1, 1, 1, 1, 1, 1]
1702
+ exp_parts_cats_col = DataFrame({"cats": cats3, "values": values3}, index=idx3)
1703
+ return exp_parts_cats_col
1704
+
1705
+ @pytest.fixture
1706
+ def exp_single_cats_value(self):
1707
+ # changed single value in cats col
1708
+ cats4 = Categorical(["a", "a", "b", "a", "a", "a", "a"], categories=["a", "b"])
1709
+ idx4 = Index(["h", "i", "j", "k", "l", "m", "n"])
1710
+ values4 = [1, 1, 1, 1, 1, 1, 1]
1711
+ exp_single_cats_value = DataFrame(
1712
+ {"cats": cats4, "values": values4}, index=idx4
1713
+ )
1714
+ return exp_single_cats_value
1715
+
1716
+ @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
1717
+ def test_loc_iloc_setitem_list_of_lists(self, orig, exp_multi_row, indexer):
1718
+ # - assign multiple rows (mixed values) -> exp_multi_row
1719
+ df = orig.copy()
1720
+
1721
+ key = slice(2, 4)
1722
+ if indexer is tm.loc:
1723
+ key = slice("j", "k")
1724
+
1725
+ indexer(df)[key, :] = [["b", 2], ["b", 2]]
1726
+ tm.assert_frame_equal(df, exp_multi_row)
1727
+
1728
+ df = orig.copy()
1729
+ with pytest.raises(TypeError, match=msg1):
1730
+ indexer(df)[key, :] = [["c", 2], ["c", 2]]
1731
+
1732
+ @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc, tm.at, tm.iat])
1733
+ def test_loc_iloc_at_iat_setitem_single_value_in_categories(
1734
+ self, orig, exp_single_cats_value, indexer
1735
+ ):
1736
+ # - assign a single value -> exp_single_cats_value
1737
+ df = orig.copy()
1738
+
1739
+ key = (2, 0)
1740
+ if indexer in [tm.loc, tm.at]:
1741
+ key = (df.index[2], df.columns[0])
1742
+
1743
+ # "b" is among the categories for df["cat"}]
1744
+ indexer(df)[key] = "b"
1745
+ tm.assert_frame_equal(df, exp_single_cats_value)
1746
+
1747
+ # "c" is not among the categories for df["cat"]
1748
+ with pytest.raises(TypeError, match=msg1):
1749
+ indexer(df)[key] = "c"
1750
+
1751
+ @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
1752
+ def test_loc_iloc_setitem_mask_single_value_in_categories(
1753
+ self, orig, exp_single_cats_value, indexer
1754
+ ):
1755
+ # mask with single True
1756
+ df = orig.copy()
1757
+
1758
+ mask = df.index == "j"
1759
+ key = 0
1760
+ if indexer is tm.loc:
1761
+ key = df.columns[key]
1762
+
1763
+ indexer(df)[mask, key] = "b"
1764
+ tm.assert_frame_equal(df, exp_single_cats_value)
1765
+
1766
+ @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
1767
+ def test_loc_iloc_setitem_full_row_non_categorical_rhs(
1768
+ self, orig, exp_single_row, indexer
1769
+ ):
1770
+ # - assign a complete row (mixed values) -> exp_single_row
1771
+ df = orig.copy()
1772
+
1773
+ key = 2
1774
+ if indexer is tm.loc:
1775
+ key = df.index[2]
1776
+
1777
+ # not categorical dtype, but "b" _is_ among the categories for df["cat"]
1778
+ indexer(df)[key, :] = ["b", 2]
1779
+ tm.assert_frame_equal(df, exp_single_row)
1780
+
1781
+ # "c" is not among the categories for df["cat"]
1782
+ with pytest.raises(TypeError, match=msg1):
1783
+ indexer(df)[key, :] = ["c", 2]
1784
+
1785
+ @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
1786
+ def test_loc_iloc_setitem_partial_col_categorical_rhs(
1787
+ self, orig, exp_parts_cats_col, indexer
1788
+ ):
1789
+ # assign a part of a column with dtype == categorical ->
1790
+ # exp_parts_cats_col
1791
+ df = orig.copy()
1792
+
1793
+ key = (slice(2, 4), 0)
1794
+ if indexer is tm.loc:
1795
+ key = (slice("j", "k"), df.columns[0])
1796
+
1797
+ # same categories as we currently have in df["cats"]
1798
+ compat = Categorical(["b", "b"], categories=["a", "b"])
1799
+ indexer(df)[key] = compat
1800
+ tm.assert_frame_equal(df, exp_parts_cats_col)
1801
+
1802
+ # categories do not match df["cat"]'s, but "b" is among them
1803
+ semi_compat = Categorical(list("bb"), categories=list("abc"))
1804
+ with pytest.raises(TypeError, match=msg2):
1805
+ # different categories but holdable values
1806
+ # -> not sure if this should fail or pass
1807
+ indexer(df)[key] = semi_compat
1808
+
1809
+ # categories do not match df["cat"]'s, and "c" is not among them
1810
+ incompat = Categorical(list("cc"), categories=list("abc"))
1811
+ with pytest.raises(TypeError, match=msg2):
1812
+ # different values
1813
+ indexer(df)[key] = incompat
1814
+
1815
+ @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
1816
+ def test_loc_iloc_setitem_non_categorical_rhs(
1817
+ self, orig, exp_parts_cats_col, indexer
1818
+ ):
1819
+ # assign a part of a column with dtype != categorical -> exp_parts_cats_col
1820
+ df = orig.copy()
1821
+
1822
+ key = (slice(2, 4), 0)
1823
+ if indexer is tm.loc:
1824
+ key = (slice("j", "k"), df.columns[0])
1825
+
1826
+ # "b" is among the categories for df["cat"]
1827
+ indexer(df)[key] = ["b", "b"]
1828
+ tm.assert_frame_equal(df, exp_parts_cats_col)
1829
+
1830
+ # "c" not part of the categories
1831
+ with pytest.raises(TypeError, match=msg1):
1832
+ indexer(df)[key] = ["c", "c"]
1833
+
1834
+ @pytest.mark.parametrize("indexer", [tm.getitem, tm.loc, tm.iloc])
1835
+ def test_getitem_preserve_object_index_with_dates(self, indexer):
1836
+ # https://github.com/pandas-dev/pandas/pull/42950 - when selecting a column
1837
+ # from dataframe, don't try to infer object dtype index on Series construction
1838
+ idx = date_range("2012", periods=3).astype(object)
1839
+ df = DataFrame({0: [1, 2, 3]}, index=idx)
1840
+ assert df.index.dtype == object
1841
+
1842
+ if indexer is tm.getitem:
1843
+ ser = indexer(df)[0]
1844
+ else:
1845
+ ser = indexer(df)[:, 0]
1846
+
1847
+ assert ser.index.dtype == object
1848
+
1849
+ def test_loc_on_multiindex_one_level(self):
1850
+ # GH#45779
1851
+ df = DataFrame(
1852
+ data=[[0], [1]],
1853
+ index=MultiIndex.from_tuples([("a",), ("b",)], names=["first"]),
1854
+ )
1855
+ expected = DataFrame(
1856
+ data=[[0]], index=MultiIndex.from_tuples([("a",)], names=["first"])
1857
+ )
1858
+ result = df.loc["a"]
1859
+ tm.assert_frame_equal(result, expected)
1860
+
1861
+
1862
+ class TestDeprecatedIndexers:
1863
+ @pytest.mark.parametrize(
1864
+ "key", [{1}, {1: 1}, ({1}, "a"), ({1: 1}, "a"), (1, {"a"}), (1, {"a": "a"})]
1865
+ )
1866
+ def test_getitem_dict_and_set_deprecated(self, key):
1867
+ # GH#42825 enforced in 2.0
1868
+ df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
1869
+ with pytest.raises(TypeError, match="as an indexer is not supported"):
1870
+ df.loc[key]
1871
+
1872
+ @pytest.mark.parametrize(
1873
+ "key",
1874
+ [
1875
+ {1},
1876
+ {1: 1},
1877
+ (({1}, 2), "a"),
1878
+ (({1: 1}, 2), "a"),
1879
+ ((1, 2), {"a"}),
1880
+ ((1, 2), {"a": "a"}),
1881
+ ],
1882
+ )
1883
+ def test_getitem_dict_and_set_deprecated_multiindex(self, key):
1884
+ # GH#42825 enforced in 2.0
1885
+ df = DataFrame(
1886
+ [[1, 2], [3, 4]],
1887
+ columns=["a", "b"],
1888
+ index=MultiIndex.from_tuples([(1, 2), (3, 4)]),
1889
+ )
1890
+ with pytest.raises(TypeError, match="as an indexer is not supported"):
1891
+ df.loc[key]
1892
+
1893
+ @pytest.mark.parametrize(
1894
+ "key", [{1}, {1: 1}, ({1}, "a"), ({1: 1}, "a"), (1, {"a"}), (1, {"a": "a"})]
1895
+ )
1896
+ def test_setitem_dict_and_set_disallowed(self, key):
1897
+ # GH#42825 enforced in 2.0
1898
+ df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
1899
+ with pytest.raises(TypeError, match="as an indexer is not supported"):
1900
+ df.loc[key] = 1
1901
+
1902
+ @pytest.mark.parametrize(
1903
+ "key",
1904
+ [
1905
+ {1},
1906
+ {1: 1},
1907
+ (({1}, 2), "a"),
1908
+ (({1: 1}, 2), "a"),
1909
+ ((1, 2), {"a"}),
1910
+ ((1, 2), {"a": "a"}),
1911
+ ],
1912
+ )
1913
+ def test_setitem_dict_and_set_disallowed_multiindex(self, key):
1914
+ # GH#42825 enforced in 2.0
1915
+ df = DataFrame(
1916
+ [[1, 2], [3, 4]],
1917
+ columns=["a", "b"],
1918
+ index=MultiIndex.from_tuples([(1, 2), (3, 4)]),
1919
+ )
1920
+ with pytest.raises(TypeError, match="as an indexer is not supported"):
1921
+ df.loc[key] = 1
1922
+
1923
+
1924
+ def test_adding_new_conditional_column() -> None:
1925
+ # https://github.com/pandas-dev/pandas/issues/55025
1926
+ df = DataFrame({"x": [1]})
1927
+ df.loc[df["x"] == 1, "y"] = "1"
1928
+ expected = DataFrame({"x": [1], "y": ["1"]})
1929
+ tm.assert_frame_equal(df, expected)
1930
+
1931
+ df = DataFrame({"x": [1]})
1932
+ # try inserting something which numpy would store as 'object'
1933
+ value = lambda x: x
1934
+ df.loc[df["x"] == 1, "y"] = value
1935
+ expected = DataFrame({"x": [1], "y": [value]})
1936
+ tm.assert_frame_equal(df, expected)
1937
+
1938
+
1939
+ @pytest.mark.parametrize(
1940
+ ("dtype", "infer_string"),
1941
+ [
1942
+ (object, False),
1943
+ ("string[pyarrow_numpy]", True),
1944
+ ],
1945
+ )
1946
+ def test_adding_new_conditional_column_with_string(dtype, infer_string) -> None:
1947
+ # https://github.com/pandas-dev/pandas/issues/56204
1948
+ pytest.importorskip("pyarrow")
1949
+
1950
+ df = DataFrame({"a": [1, 2], "b": [3, 4]})
1951
+ with pd.option_context("future.infer_string", infer_string):
1952
+ df.loc[df["a"] == 1, "c"] = "1"
1953
+ expected = DataFrame({"a": [1, 2], "b": [3, 4], "c": ["1", float("nan")]}).astype(
1954
+ {"a": "int64", "b": "int64", "c": dtype}
1955
+ )
1956
+ tm.assert_frame_equal(df, expected)
1957
+
1958
+
1959
+ def test_add_new_column_infer_string():
1960
+ # GH#55366
1961
+ pytest.importorskip("pyarrow")
1962
+ df = DataFrame({"x": [1]})
1963
+ with pd.option_context("future.infer_string", True):
1964
+ df.loc[df["x"] == 1, "y"] = "1"
1965
+ expected = DataFrame(
1966
+ {"x": [1], "y": Series(["1"], dtype="string[pyarrow_numpy]")},
1967
+ columns=Index(["x", "y"], dtype=object),
1968
+ )
1969
+ tm.assert_frame_equal(df, expected)
1970
+
1971
+
1972
+ class TestSetitemValidation:
1973
+ # This is adapted from pandas/tests/arrays/masked/test_indexing.py
1974
+ # but checks for warnings instead of errors.
1975
+ def _check_setitem_invalid(self, df, invalid, indexer, warn):
1976
+ msg = "Setting an item of incompatible dtype is deprecated"
1977
+ msg = re.escape(msg)
1978
+
1979
+ orig_df = df.copy()
1980
+
1981
+ # iloc
1982
+ with tm.assert_produces_warning(warn, match=msg):
1983
+ df.iloc[indexer, 0] = invalid
1984
+ df = orig_df.copy()
1985
+
1986
+ # loc
1987
+ with tm.assert_produces_warning(warn, match=msg):
1988
+ df.loc[indexer, "a"] = invalid
1989
+ df = orig_df.copy()
1990
+
1991
+ _invalid_scalars = [
1992
+ 1 + 2j,
1993
+ "True",
1994
+ "1",
1995
+ "1.0",
1996
+ pd.NaT,
1997
+ np.datetime64("NaT"),
1998
+ np.timedelta64("NaT"),
1999
+ ]
2000
+ _indexers = [0, [0], slice(0, 1), [True, False, False], slice(None, None, None)]
2001
+
2002
+ @pytest.mark.parametrize(
2003
+ "invalid", _invalid_scalars + [1, 1.0, np.int64(1), np.float64(1)]
2004
+ )
2005
+ @pytest.mark.parametrize("indexer", _indexers)
2006
+ def test_setitem_validation_scalar_bool(self, invalid, indexer):
2007
+ df = DataFrame({"a": [True, False, False]}, dtype="bool")
2008
+ self._check_setitem_invalid(df, invalid, indexer, FutureWarning)
2009
+
2010
+ @pytest.mark.parametrize("invalid", _invalid_scalars + [True, 1.5, np.float64(1.5)])
2011
+ @pytest.mark.parametrize("indexer", _indexers)
2012
+ def test_setitem_validation_scalar_int(self, invalid, any_int_numpy_dtype, indexer):
2013
+ df = DataFrame({"a": [1, 2, 3]}, dtype=any_int_numpy_dtype)
2014
+ if isna(invalid) and invalid is not pd.NaT and not np.isnat(invalid):
2015
+ warn = None
2016
+ else:
2017
+ warn = FutureWarning
2018
+ self._check_setitem_invalid(df, invalid, indexer, warn)
2019
+
2020
+ @pytest.mark.parametrize("invalid", _invalid_scalars + [True])
2021
+ @pytest.mark.parametrize("indexer", _indexers)
2022
+ def test_setitem_validation_scalar_float(self, invalid, float_numpy_dtype, indexer):
2023
+ df = DataFrame({"a": [1, 2, None]}, dtype=float_numpy_dtype)
2024
+ self._check_setitem_invalid(df, invalid, indexer, FutureWarning)
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_insert.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ test_insert is specifically for the DataFrame.insert method; not to be
3
+ confused with tests with "insert" in their names that are really testing
4
+ __setitem__.
5
+ """
6
+ import numpy as np
7
+ import pytest
8
+
9
+ from pandas.errors import PerformanceWarning
10
+
11
+ from pandas import (
12
+ DataFrame,
13
+ Index,
14
+ )
15
+ import pandas._testing as tm
16
+
17
+
18
+ class TestDataFrameInsert:
19
+ def test_insert(self):
20
+ df = DataFrame(
21
+ np.random.default_rng(2).standard_normal((5, 3)),
22
+ index=np.arange(5),
23
+ columns=["c", "b", "a"],
24
+ )
25
+
26
+ df.insert(0, "foo", df["a"])
27
+ tm.assert_index_equal(df.columns, Index(["foo", "c", "b", "a"]))
28
+ tm.assert_series_equal(df["a"], df["foo"], check_names=False)
29
+
30
+ df.insert(2, "bar", df["c"])
31
+ tm.assert_index_equal(df.columns, Index(["foo", "c", "bar", "b", "a"]))
32
+ tm.assert_almost_equal(df["c"], df["bar"], check_names=False)
33
+
34
+ with pytest.raises(ValueError, match="already exists"):
35
+ df.insert(1, "a", df["b"])
36
+
37
+ msg = "cannot insert c, already exists"
38
+ with pytest.raises(ValueError, match=msg):
39
+ df.insert(1, "c", df["b"])
40
+
41
+ df.columns.name = "some_name"
42
+ # preserve columns name field
43
+ df.insert(0, "baz", df["c"])
44
+ assert df.columns.name == "some_name"
45
+
46
+ def test_insert_column_bug_4032(self):
47
+ # GH#4032, inserting a column and renaming causing errors
48
+ df = DataFrame({"b": [1.1, 2.2]})
49
+
50
+ df = df.rename(columns={})
51
+ df.insert(0, "a", [1, 2])
52
+ result = df.rename(columns={})
53
+
54
+ expected = DataFrame([[1, 1.1], [2, 2.2]], columns=["a", "b"])
55
+ tm.assert_frame_equal(result, expected)
56
+
57
+ df.insert(0, "c", [1.3, 2.3])
58
+ result = df.rename(columns={})
59
+
60
+ expected = DataFrame([[1.3, 1, 1.1], [2.3, 2, 2.2]], columns=["c", "a", "b"])
61
+ tm.assert_frame_equal(result, expected)
62
+
63
+ def test_insert_with_columns_dups(self):
64
+ # GH#14291
65
+ df = DataFrame()
66
+ df.insert(0, "A", ["g", "h", "i"], allow_duplicates=True)
67
+ df.insert(0, "A", ["d", "e", "f"], allow_duplicates=True)
68
+ df.insert(0, "A", ["a", "b", "c"], allow_duplicates=True)
69
+ exp = DataFrame(
70
+ [["a", "d", "g"], ["b", "e", "h"], ["c", "f", "i"]], columns=["A", "A", "A"]
71
+ )
72
+ tm.assert_frame_equal(df, exp)
73
+
74
+ def test_insert_item_cache(self, using_array_manager, using_copy_on_write):
75
+ df = DataFrame(np.random.default_rng(2).standard_normal((4, 3)))
76
+ ser = df[0]
77
+
78
+ if using_array_manager:
79
+ expected_warning = None
80
+ else:
81
+ # with BlockManager warn about high fragmentation of single dtype
82
+ expected_warning = PerformanceWarning
83
+
84
+ with tm.assert_produces_warning(expected_warning):
85
+ for n in range(100):
86
+ df[n + 3] = df[1] * n
87
+
88
+ if using_copy_on_write:
89
+ ser.iloc[0] = 99
90
+ assert df.iloc[0, 0] == df[0][0]
91
+ assert df.iloc[0, 0] != 99
92
+ else:
93
+ ser.values[0] = 99
94
+ assert df.iloc[0, 0] == df[0][0]
95
+ assert df.iloc[0, 0] == 99
96
+
97
+ def test_insert_EA_no_warning(self):
98
+ # PerformanceWarning about fragmented frame should not be raised when
99
+ # using EAs (https://github.com/pandas-dev/pandas/issues/44098)
100
+ df = DataFrame(
101
+ np.random.default_rng(2).integers(0, 100, size=(3, 100)), dtype="Int64"
102
+ )
103
+ with tm.assert_produces_warning(None):
104
+ df["a"] = np.array([1, 2, 3])
105
+
106
+ def test_insert_frame(self):
107
+ # GH#42403
108
+ df = DataFrame({"col1": [1, 2], "col2": [3, 4]})
109
+
110
+ msg = (
111
+ "Expected a one-dimensional object, got a DataFrame with 2 columns instead."
112
+ )
113
+ with pytest.raises(ValueError, match=msg):
114
+ df.insert(1, "newcol", df)
115
+
116
+ def test_insert_int64_loc(self):
117
+ # GH#53193
118
+ df = DataFrame({"a": [1, 2]})
119
+ df.insert(np.int64(0), "b", 0)
120
+ tm.assert_frame_equal(df, DataFrame({"b": [0, 0], "a": [1, 2]}))
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_mask.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for DataFrame.mask; tests DataFrame.where as a side-effect.
3
+ """
4
+
5
+ import numpy as np
6
+
7
+ from pandas import (
8
+ NA,
9
+ DataFrame,
10
+ Float64Dtype,
11
+ Series,
12
+ StringDtype,
13
+ Timedelta,
14
+ isna,
15
+ )
16
+ import pandas._testing as tm
17
+
18
+
19
+ class TestDataFrameMask:
20
+ def test_mask(self):
21
+ df = DataFrame(np.random.default_rng(2).standard_normal((5, 3)))
22
+ cond = df > 0
23
+
24
+ rs = df.where(cond, np.nan)
25
+ tm.assert_frame_equal(rs, df.mask(df <= 0))
26
+ tm.assert_frame_equal(rs, df.mask(~cond))
27
+
28
+ other = DataFrame(np.random.default_rng(2).standard_normal((5, 3)))
29
+ rs = df.where(cond, other)
30
+ tm.assert_frame_equal(rs, df.mask(df <= 0, other))
31
+ tm.assert_frame_equal(rs, df.mask(~cond, other))
32
+
33
+ def test_mask2(self):
34
+ # see GH#21891
35
+ df = DataFrame([1, 2])
36
+ res = df.mask([[True], [False]])
37
+
38
+ exp = DataFrame([np.nan, 2])
39
+ tm.assert_frame_equal(res, exp)
40
+
41
+ def test_mask_inplace(self):
42
+ # GH#8801
43
+ df = DataFrame(np.random.default_rng(2).standard_normal((5, 3)))
44
+ cond = df > 0
45
+
46
+ rdf = df.copy()
47
+
48
+ return_value = rdf.where(cond, inplace=True)
49
+ assert return_value is None
50
+ tm.assert_frame_equal(rdf, df.where(cond))
51
+ tm.assert_frame_equal(rdf, df.mask(~cond))
52
+
53
+ rdf = df.copy()
54
+ return_value = rdf.where(cond, -df, inplace=True)
55
+ assert return_value is None
56
+ tm.assert_frame_equal(rdf, df.where(cond, -df))
57
+ tm.assert_frame_equal(rdf, df.mask(~cond, -df))
58
+
59
+ def test_mask_edge_case_1xN_frame(self):
60
+ # GH#4071
61
+ df = DataFrame([[1, 2]])
62
+ res = df.mask(DataFrame([[True, False]]))
63
+ expec = DataFrame([[np.nan, 2]])
64
+ tm.assert_frame_equal(res, expec)
65
+
66
+ def test_mask_callable(self):
67
+ # GH#12533
68
+ df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
69
+ result = df.mask(lambda x: x > 4, lambda x: x + 1)
70
+ exp = DataFrame([[1, 2, 3], [4, 6, 7], [8, 9, 10]])
71
+ tm.assert_frame_equal(result, exp)
72
+ tm.assert_frame_equal(result, df.mask(df > 4, df + 1))
73
+
74
+ # return ndarray and scalar
75
+ result = df.mask(lambda x: (x % 2 == 0).values, lambda x: 99)
76
+ exp = DataFrame([[1, 99, 3], [99, 5, 99], [7, 99, 9]])
77
+ tm.assert_frame_equal(result, exp)
78
+ tm.assert_frame_equal(result, df.mask(df % 2 == 0, 99))
79
+
80
+ # chain
81
+ result = (df + 2).mask(lambda x: x > 8, lambda x: x + 10)
82
+ exp = DataFrame([[3, 4, 5], [6, 7, 8], [19, 20, 21]])
83
+ tm.assert_frame_equal(result, exp)
84
+ tm.assert_frame_equal(result, (df + 2).mask((df + 2) > 8, (df + 2) + 10))
85
+
86
+ def test_mask_dtype_bool_conversion(self):
87
+ # GH#3733
88
+ df = DataFrame(data=np.random.default_rng(2).standard_normal((100, 50)))
89
+ df = df.where(df > 0) # create nans
90
+ bools = df > 0
91
+ mask = isna(df)
92
+ expected = bools.astype(object).mask(mask)
93
+ result = bools.mask(mask)
94
+ tm.assert_frame_equal(result, expected)
95
+
96
+
97
+ def test_mask_stringdtype(frame_or_series):
98
+ # GH 40824
99
+ obj = DataFrame(
100
+ {"A": ["foo", "bar", "baz", NA]},
101
+ index=["id1", "id2", "id3", "id4"],
102
+ dtype=StringDtype(),
103
+ )
104
+ filtered_obj = DataFrame(
105
+ {"A": ["this", "that"]}, index=["id2", "id3"], dtype=StringDtype()
106
+ )
107
+ expected = DataFrame(
108
+ {"A": [NA, "this", "that", NA]},
109
+ index=["id1", "id2", "id3", "id4"],
110
+ dtype=StringDtype(),
111
+ )
112
+ if frame_or_series is Series:
113
+ obj = obj["A"]
114
+ filtered_obj = filtered_obj["A"]
115
+ expected = expected["A"]
116
+
117
+ filter_ser = Series([False, True, True, False])
118
+ result = obj.mask(filter_ser, filtered_obj)
119
+
120
+ tm.assert_equal(result, expected)
121
+
122
+
123
+ def test_mask_where_dtype_timedelta():
124
+ # https://github.com/pandas-dev/pandas/issues/39548
125
+ df = DataFrame([Timedelta(i, unit="d") for i in range(5)])
126
+
127
+ expected = DataFrame(np.full(5, np.nan, dtype="timedelta64[ns]"))
128
+ tm.assert_frame_equal(df.mask(df.notna()), expected)
129
+
130
+ expected = DataFrame(
131
+ [np.nan, np.nan, np.nan, Timedelta("3 day"), Timedelta("4 day")]
132
+ )
133
+ tm.assert_frame_equal(df.where(df > Timedelta(2, unit="d")), expected)
134
+
135
+
136
+ def test_mask_return_dtype():
137
+ # GH#50488
138
+ ser = Series([0.0, 1.0, 2.0, 3.0], dtype=Float64Dtype())
139
+ cond = ~ser.isna()
140
+ other = Series([True, False, True, False])
141
+ excepted = Series([1.0, 0.0, 1.0, 0.0], dtype=ser.dtype)
142
+ result = ser.mask(cond, other)
143
+ tm.assert_series_equal(result, excepted)
144
+
145
+
146
+ def test_mask_inplace_no_other():
147
+ # GH#51685
148
+ df = DataFrame({"a": [1.0, 2.0], "b": ["x", "y"]})
149
+ cond = DataFrame({"a": [True, False], "b": [False, True]})
150
+ df.mask(cond, inplace=True)
151
+ expected = DataFrame({"a": [np.nan, 2], "b": ["x", np.nan]})
152
+ tm.assert_frame_equal(df, expected)
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_set_value.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ from pandas.core.dtypes.common import is_float_dtype
4
+
5
+ from pandas import (
6
+ DataFrame,
7
+ isna,
8
+ )
9
+ import pandas._testing as tm
10
+
11
+
12
+ class TestSetValue:
13
+ def test_set_value(self, float_frame):
14
+ for idx in float_frame.index:
15
+ for col in float_frame.columns:
16
+ float_frame._set_value(idx, col, 1)
17
+ assert float_frame[col][idx] == 1
18
+
19
+ def test_set_value_resize(self, float_frame, using_infer_string):
20
+ res = float_frame._set_value("foobar", "B", 0)
21
+ assert res is None
22
+ assert float_frame.index[-1] == "foobar"
23
+ assert float_frame._get_value("foobar", "B") == 0
24
+
25
+ float_frame.loc["foobar", "qux"] = 0
26
+ assert float_frame._get_value("foobar", "qux") == 0
27
+
28
+ res = float_frame.copy()
29
+ res._set_value("foobar", "baz", "sam")
30
+ if using_infer_string:
31
+ assert res["baz"].dtype == "string"
32
+ else:
33
+ assert res["baz"].dtype == np.object_
34
+ res = float_frame.copy()
35
+ res._set_value("foobar", "baz", True)
36
+ assert res["baz"].dtype == np.object_
37
+
38
+ res = float_frame.copy()
39
+ res._set_value("foobar", "baz", 5)
40
+ assert is_float_dtype(res["baz"])
41
+ assert isna(res["baz"].drop(["foobar"])).all()
42
+
43
+ with tm.assert_produces_warning(
44
+ FutureWarning, match="Setting an item of incompatible dtype"
45
+ ):
46
+ res._set_value("foobar", "baz", "sam")
47
+ assert res.loc["foobar", "baz"] == "sam"
48
+
49
+ def test_set_value_with_index_dtype_change(self):
50
+ df_orig = DataFrame(
51
+ np.random.default_rng(2).standard_normal((3, 3)),
52
+ index=range(3),
53
+ columns=list("ABC"),
54
+ )
55
+
56
+ # this is actually ambiguous as the 2 is interpreted as a positional
57
+ # so column is not created
58
+ df = df_orig.copy()
59
+ df._set_value("C", 2, 1.0)
60
+ assert list(df.index) == list(df_orig.index) + ["C"]
61
+ # assert list(df.columns) == list(df_orig.columns) + [2]
62
+
63
+ df = df_orig.copy()
64
+ df.loc["C", 2] = 1.0
65
+ assert list(df.index) == list(df_orig.index) + ["C"]
66
+ # assert list(df.columns) == list(df_orig.columns) + [2]
67
+
68
+ # create both new
69
+ df = df_orig.copy()
70
+ df._set_value("C", "D", 1.0)
71
+ assert list(df.index) == list(df_orig.index) + ["C"]
72
+ assert list(df.columns) == list(df_orig.columns) + ["D"]
73
+
74
+ df = df_orig.copy()
75
+ df.loc["C", "D"] = 1.0
76
+ assert list(df.index) == list(df_orig.index) + ["C"]
77
+ assert list(df.columns) == list(df_orig.columns) + ["D"]
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_setitem.py ADDED
@@ -0,0 +1,1419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ import pandas.util._test_decorators as td
7
+
8
+ from pandas.core.dtypes.base import _registry as ea_registry
9
+ from pandas.core.dtypes.common import is_object_dtype
10
+ from pandas.core.dtypes.dtypes import (
11
+ CategoricalDtype,
12
+ DatetimeTZDtype,
13
+ IntervalDtype,
14
+ PeriodDtype,
15
+ )
16
+
17
+ import pandas as pd
18
+ from pandas import (
19
+ Categorical,
20
+ DataFrame,
21
+ DatetimeIndex,
22
+ Index,
23
+ Interval,
24
+ IntervalIndex,
25
+ MultiIndex,
26
+ NaT,
27
+ Period,
28
+ PeriodIndex,
29
+ Series,
30
+ Timestamp,
31
+ cut,
32
+ date_range,
33
+ notna,
34
+ period_range,
35
+ )
36
+ import pandas._testing as tm
37
+ from pandas.core.arrays import SparseArray
38
+
39
+ from pandas.tseries.offsets import BDay
40
+
41
+
42
+ class TestDataFrameSetItem:
43
+ def test_setitem_str_subclass(self):
44
+ # GH#37366
45
+ class mystring(str):
46
+ pass
47
+
48
+ data = ["2020-10-22 01:21:00+00:00"]
49
+ index = DatetimeIndex(data)
50
+ df = DataFrame({"a": [1]}, index=index)
51
+ df["b"] = 2
52
+ df[mystring("c")] = 3
53
+ expected = DataFrame({"a": [1], "b": [2], mystring("c"): [3]}, index=index)
54
+ tm.assert_equal(df, expected)
55
+
56
+ @pytest.mark.parametrize(
57
+ "dtype", ["int32", "int64", "uint32", "uint64", "float32", "float64"]
58
+ )
59
+ def test_setitem_dtype(self, dtype, float_frame):
60
+ # Use integers since casting negative floats to uints is undefined
61
+ arr = np.random.default_rng(2).integers(1, 10, len(float_frame))
62
+
63
+ float_frame[dtype] = np.array(arr, dtype=dtype)
64
+ assert float_frame[dtype].dtype.name == dtype
65
+
66
+ def test_setitem_list_not_dataframe(self, float_frame):
67
+ data = np.random.default_rng(2).standard_normal((len(float_frame), 2))
68
+ float_frame[["A", "B"]] = data
69
+ tm.assert_almost_equal(float_frame[["A", "B"]].values, data)
70
+
71
+ def test_setitem_error_msmgs(self):
72
+ # GH 7432
73
+ df = DataFrame(
74
+ {"bar": [1, 2, 3], "baz": ["d", "e", "f"]},
75
+ index=Index(["a", "b", "c"], name="foo"),
76
+ )
77
+ ser = Series(
78
+ ["g", "h", "i", "j"],
79
+ index=Index(["a", "b", "c", "a"], name="foo"),
80
+ name="fiz",
81
+ )
82
+ msg = "cannot reindex on an axis with duplicate labels"
83
+ with pytest.raises(ValueError, match=msg):
84
+ df["newcol"] = ser
85
+
86
+ # GH 4107, more descriptive error message
87
+ df = DataFrame(
88
+ np.random.default_rng(2).integers(0, 2, (4, 4)),
89
+ columns=["a", "b", "c", "d"],
90
+ )
91
+
92
+ msg = "Cannot set a DataFrame with multiple columns to the single column gr"
93
+ with pytest.raises(ValueError, match=msg):
94
+ df["gr"] = df.groupby(["b", "c"]).count()
95
+
96
+ # GH 55956, specific message for zero columns
97
+ msg = "Cannot set a DataFrame without columns to the column gr"
98
+ with pytest.raises(ValueError, match=msg):
99
+ df["gr"] = DataFrame()
100
+
101
+ def test_setitem_benchmark(self):
102
+ # from the vb_suite/frame_methods/frame_insert_columns
103
+ N = 10
104
+ K = 5
105
+ df = DataFrame(index=range(N))
106
+ new_col = np.random.default_rng(2).standard_normal(N)
107
+ for i in range(K):
108
+ df[i] = new_col
109
+ expected = DataFrame(np.repeat(new_col, K).reshape(N, K), index=range(N))
110
+ tm.assert_frame_equal(df, expected)
111
+
112
+ def test_setitem_different_dtype(self):
113
+ df = DataFrame(
114
+ np.random.default_rng(2).standard_normal((5, 3)),
115
+ index=np.arange(5),
116
+ columns=["c", "b", "a"],
117
+ )
118
+ df.insert(0, "foo", df["a"])
119
+ df.insert(2, "bar", df["c"])
120
+
121
+ # diff dtype
122
+
123
+ # new item
124
+ df["x"] = df["a"].astype("float32")
125
+ result = df.dtypes
126
+ expected = Series(
127
+ [np.dtype("float64")] * 5 + [np.dtype("float32")],
128
+ index=["foo", "c", "bar", "b", "a", "x"],
129
+ )
130
+ tm.assert_series_equal(result, expected)
131
+
132
+ # replacing current (in different block)
133
+ df["a"] = df["a"].astype("float32")
134
+ result = df.dtypes
135
+ expected = Series(
136
+ [np.dtype("float64")] * 4 + [np.dtype("float32")] * 2,
137
+ index=["foo", "c", "bar", "b", "a", "x"],
138
+ )
139
+ tm.assert_series_equal(result, expected)
140
+
141
+ df["y"] = df["a"].astype("int32")
142
+ result = df.dtypes
143
+ expected = Series(
144
+ [np.dtype("float64")] * 4 + [np.dtype("float32")] * 2 + [np.dtype("int32")],
145
+ index=["foo", "c", "bar", "b", "a", "x", "y"],
146
+ )
147
+ tm.assert_series_equal(result, expected)
148
+
149
+ def test_setitem_empty_columns(self):
150
+ # GH 13522
151
+ df = DataFrame(index=["A", "B", "C"])
152
+ df["X"] = df.index
153
+ df["X"] = ["x", "y", "z"]
154
+ exp = DataFrame(data={"X": ["x", "y", "z"]}, index=["A", "B", "C"])
155
+ tm.assert_frame_equal(df, exp)
156
+
157
+ def test_setitem_dt64_index_empty_columns(self):
158
+ rng = date_range("1/1/2000 00:00:00", "1/1/2000 1:59:50", freq="10s")
159
+ df = DataFrame(index=np.arange(len(rng)))
160
+
161
+ df["A"] = rng
162
+ assert df["A"].dtype == np.dtype("M8[ns]")
163
+
164
+ def test_setitem_timestamp_empty_columns(self):
165
+ # GH#19843
166
+ df = DataFrame(index=range(3))
167
+ df["now"] = Timestamp("20130101", tz="UTC").as_unit("ns")
168
+
169
+ expected = DataFrame(
170
+ [[Timestamp("20130101", tz="UTC")]] * 3, index=[0, 1, 2], columns=["now"]
171
+ )
172
+ tm.assert_frame_equal(df, expected)
173
+
174
+ def test_setitem_wrong_length_categorical_dtype_raises(self):
175
+ # GH#29523
176
+ cat = Categorical.from_codes([0, 1, 1, 0, 1, 2], ["a", "b", "c"])
177
+ df = DataFrame(range(10), columns=["bar"])
178
+
179
+ msg = (
180
+ rf"Length of values \({len(cat)}\) "
181
+ rf"does not match length of index \({len(df)}\)"
182
+ )
183
+ with pytest.raises(ValueError, match=msg):
184
+ df["foo"] = cat
185
+
186
+ def test_setitem_with_sparse_value(self):
187
+ # GH#8131
188
+ df = DataFrame({"c_1": ["a", "b", "c"], "n_1": [1.0, 2.0, 3.0]})
189
+ sp_array = SparseArray([0, 0, 1])
190
+ df["new_column"] = sp_array
191
+
192
+ expected = Series(sp_array, name="new_column")
193
+ tm.assert_series_equal(df["new_column"], expected)
194
+
195
+ def test_setitem_with_unaligned_sparse_value(self):
196
+ df = DataFrame({"c_1": ["a", "b", "c"], "n_1": [1.0, 2.0, 3.0]})
197
+ sp_series = Series(SparseArray([0, 0, 1]), index=[2, 1, 0])
198
+
199
+ df["new_column"] = sp_series
200
+ expected = Series(SparseArray([1, 0, 0]), name="new_column")
201
+ tm.assert_series_equal(df["new_column"], expected)
202
+
203
+ def test_setitem_period_preserves_dtype(self):
204
+ # GH: 26861
205
+ data = [Period("2003-12", "D")]
206
+ result = DataFrame([])
207
+ result["a"] = data
208
+
209
+ expected = DataFrame({"a": data})
210
+
211
+ tm.assert_frame_equal(result, expected)
212
+
213
+ def test_setitem_dict_preserves_dtypes(self):
214
+ # https://github.com/pandas-dev/pandas/issues/34573
215
+ expected = DataFrame(
216
+ {
217
+ "a": Series([0, 1, 2], dtype="int64"),
218
+ "b": Series([1, 2, 3], dtype=float),
219
+ "c": Series([1, 2, 3], dtype=float),
220
+ "d": Series([1, 2, 3], dtype="uint32"),
221
+ }
222
+ )
223
+ df = DataFrame(
224
+ {
225
+ "a": Series([], dtype="int64"),
226
+ "b": Series([], dtype=float),
227
+ "c": Series([], dtype=float),
228
+ "d": Series([], dtype="uint32"),
229
+ }
230
+ )
231
+ for idx, b in enumerate([1, 2, 3]):
232
+ df.loc[df.shape[0]] = {
233
+ "a": int(idx),
234
+ "b": float(b),
235
+ "c": float(b),
236
+ "d": np.uint32(b),
237
+ }
238
+ tm.assert_frame_equal(df, expected)
239
+
240
+ @pytest.mark.parametrize(
241
+ "obj,dtype",
242
+ [
243
+ (Period("2020-01"), PeriodDtype("M")),
244
+ (Interval(left=0, right=5), IntervalDtype("int64", "right")),
245
+ (
246
+ Timestamp("2011-01-01", tz="US/Eastern"),
247
+ DatetimeTZDtype(unit="s", tz="US/Eastern"),
248
+ ),
249
+ ],
250
+ )
251
+ def test_setitem_extension_types(self, obj, dtype):
252
+ # GH: 34832
253
+ expected = DataFrame({"idx": [1, 2, 3], "obj": Series([obj] * 3, dtype=dtype)})
254
+
255
+ df = DataFrame({"idx": [1, 2, 3]})
256
+ df["obj"] = obj
257
+
258
+ tm.assert_frame_equal(df, expected)
259
+
260
+ @pytest.mark.parametrize(
261
+ "ea_name",
262
+ [
263
+ dtype.name
264
+ for dtype in ea_registry.dtypes
265
+ # property would require instantiation
266
+ if not isinstance(dtype.name, property)
267
+ ]
268
+ + ["datetime64[ns, UTC]", "period[D]"],
269
+ )
270
+ def test_setitem_with_ea_name(self, ea_name):
271
+ # GH 38386
272
+ result = DataFrame([0])
273
+ result[ea_name] = [1]
274
+ expected = DataFrame({0: [0], ea_name: [1]})
275
+ tm.assert_frame_equal(result, expected)
276
+
277
+ def test_setitem_dt64_ndarray_with_NaT_and_diff_time_units(self):
278
+ # GH#7492
279
+ data_ns = np.array([1, "nat"], dtype="datetime64[ns]")
280
+ result = Series(data_ns).to_frame()
281
+ result["new"] = data_ns
282
+ expected = DataFrame({0: [1, None], "new": [1, None]}, dtype="datetime64[ns]")
283
+ tm.assert_frame_equal(result, expected)
284
+
285
+ # OutOfBoundsDatetime error shouldn't occur; as of 2.0 we preserve "M8[s]"
286
+ data_s = np.array([1, "nat"], dtype="datetime64[s]")
287
+ result["new"] = data_s
288
+ tm.assert_series_equal(result[0], expected[0])
289
+ tm.assert_numpy_array_equal(result["new"].to_numpy(), data_s)
290
+
291
+ @pytest.mark.parametrize("unit", ["h", "m", "s", "ms", "D", "M", "Y"])
292
+ def test_frame_setitem_datetime64_col_other_units(self, unit):
293
+ # Check that non-nano dt64 values get cast to dt64 on setitem
294
+ # into a not-yet-existing column
295
+ n = 100
296
+
297
+ dtype = np.dtype(f"M8[{unit}]")
298
+ vals = np.arange(n, dtype=np.int64).view(dtype)
299
+ if unit in ["s", "ms"]:
300
+ # supported unit
301
+ ex_vals = vals
302
+ else:
303
+ # we get the nearest supported units, i.e. "s"
304
+ ex_vals = vals.astype("datetime64[s]")
305
+
306
+ df = DataFrame({"ints": np.arange(n)}, index=np.arange(n))
307
+ df[unit] = vals
308
+
309
+ assert df[unit].dtype == ex_vals.dtype
310
+ assert (df[unit].values == ex_vals).all()
311
+
312
+ @pytest.mark.parametrize("unit", ["h", "m", "s", "ms", "D", "M", "Y"])
313
+ def test_frame_setitem_existing_datetime64_col_other_units(self, unit):
314
+ # Check that non-nano dt64 values get cast to dt64 on setitem
315
+ # into an already-existing dt64 column
316
+ n = 100
317
+
318
+ dtype = np.dtype(f"M8[{unit}]")
319
+ vals = np.arange(n, dtype=np.int64).view(dtype)
320
+ ex_vals = vals.astype("datetime64[ns]")
321
+
322
+ df = DataFrame({"ints": np.arange(n)}, index=np.arange(n))
323
+ df["dates"] = np.arange(n, dtype=np.int64).view("M8[ns]")
324
+
325
+ # We overwrite existing dt64 column with new, non-nano dt64 vals
326
+ df["dates"] = vals
327
+ assert (df["dates"].values == ex_vals).all()
328
+
329
+ def test_setitem_dt64tz(self, timezone_frame, using_copy_on_write):
330
+ df = timezone_frame
331
+ idx = df["B"].rename("foo")
332
+
333
+ # setitem
334
+ df["C"] = idx
335
+ tm.assert_series_equal(df["C"], Series(idx, name="C"))
336
+
337
+ df["D"] = "foo"
338
+ df["D"] = idx
339
+ tm.assert_series_equal(df["D"], Series(idx, name="D"))
340
+ del df["D"]
341
+
342
+ # assert that A & C are not sharing the same base (e.g. they
343
+ # are copies)
344
+ # Note: This does not hold with Copy on Write (because of lazy copying)
345
+ v1 = df._mgr.arrays[1]
346
+ v2 = df._mgr.arrays[2]
347
+ tm.assert_extension_array_equal(v1, v2)
348
+ v1base = v1._ndarray.base
349
+ v2base = v2._ndarray.base
350
+ if not using_copy_on_write:
351
+ assert v1base is None or (id(v1base) != id(v2base))
352
+ else:
353
+ assert id(v1base) == id(v2base)
354
+
355
+ # with nan
356
+ df2 = df.copy()
357
+ df2.iloc[1, 1] = NaT
358
+ df2.iloc[1, 2] = NaT
359
+ result = df2["B"]
360
+ tm.assert_series_equal(notna(result), Series([True, False, True], name="B"))
361
+ tm.assert_series_equal(df2.dtypes, df.dtypes)
362
+
363
+ def test_setitem_periodindex(self):
364
+ rng = period_range("1/1/2000", periods=5, name="index")
365
+ df = DataFrame(np.random.default_rng(2).standard_normal((5, 3)), index=rng)
366
+
367
+ df["Index"] = rng
368
+ rs = Index(df["Index"])
369
+ tm.assert_index_equal(rs, rng, check_names=False)
370
+ assert rs.name == "Index"
371
+ assert rng.name == "index"
372
+
373
+ rs = df.reset_index().set_index("index")
374
+ assert isinstance(rs.index, PeriodIndex)
375
+ tm.assert_index_equal(rs.index, rng)
376
+
377
+ def test_setitem_complete_column_with_array(self):
378
+ # GH#37954
379
+ df = DataFrame({"a": ["one", "two", "three"], "b": [1, 2, 3]})
380
+ arr = np.array([[1, 1], [3, 1], [5, 1]])
381
+ df[["c", "d"]] = arr
382
+ expected = DataFrame(
383
+ {
384
+ "a": ["one", "two", "three"],
385
+ "b": [1, 2, 3],
386
+ "c": [1, 3, 5],
387
+ "d": [1, 1, 1],
388
+ }
389
+ )
390
+ expected["c"] = expected["c"].astype(arr.dtype)
391
+ expected["d"] = expected["d"].astype(arr.dtype)
392
+ assert expected["c"].dtype == arr.dtype
393
+ assert expected["d"].dtype == arr.dtype
394
+ tm.assert_frame_equal(df, expected)
395
+
396
+ def test_setitem_period_d_dtype(self):
397
+ # GH 39763
398
+ rng = period_range("2016-01-01", periods=9, freq="D", name="A")
399
+ result = DataFrame(rng)
400
+ expected = DataFrame(
401
+ {"A": ["NaT", "NaT", "NaT", "NaT", "NaT", "NaT", "NaT", "NaT", "NaT"]},
402
+ dtype="period[D]",
403
+ )
404
+ result.iloc[:] = rng._na_value
405
+ tm.assert_frame_equal(result, expected)
406
+
407
+ @pytest.mark.parametrize("dtype", ["f8", "i8", "u8"])
408
+ def test_setitem_bool_with_numeric_index(self, dtype):
409
+ # GH#36319
410
+ cols = Index([1, 2, 3], dtype=dtype)
411
+ df = DataFrame(np.random.default_rng(2).standard_normal((3, 3)), columns=cols)
412
+
413
+ df[False] = ["a", "b", "c"]
414
+
415
+ expected_cols = Index([1, 2, 3, False], dtype=object)
416
+ if dtype == "f8":
417
+ expected_cols = Index([1.0, 2.0, 3.0, False], dtype=object)
418
+
419
+ tm.assert_index_equal(df.columns, expected_cols)
420
+
421
+ @pytest.mark.parametrize("indexer", ["B", ["B"]])
422
+ def test_setitem_frame_length_0_str_key(self, indexer):
423
+ # GH#38831
424
+ df = DataFrame(columns=["A", "B"])
425
+ other = DataFrame({"B": [1, 2]})
426
+ df[indexer] = other
427
+ expected = DataFrame({"A": [np.nan] * 2, "B": [1, 2]})
428
+ expected["A"] = expected["A"].astype("object")
429
+ tm.assert_frame_equal(df, expected)
430
+
431
+ def test_setitem_frame_duplicate_columns(self):
432
+ # GH#15695
433
+ cols = ["A", "B", "C"] * 2
434
+ df = DataFrame(index=range(3), columns=cols)
435
+ df.loc[0, "A"] = (0, 3)
436
+ df.loc[:, "B"] = (1, 4)
437
+ df["C"] = (2, 5)
438
+ expected = DataFrame(
439
+ [
440
+ [0, 1, 2, 3, 4, 5],
441
+ [np.nan, 1, 2, np.nan, 4, 5],
442
+ [np.nan, 1, 2, np.nan, 4, 5],
443
+ ],
444
+ dtype="object",
445
+ )
446
+
447
+ # set these with unique columns to be extra-unambiguous
448
+ expected[2] = expected[2].astype(np.int64)
449
+ expected[5] = expected[5].astype(np.int64)
450
+ expected.columns = cols
451
+
452
+ tm.assert_frame_equal(df, expected)
453
+
454
+ def test_setitem_frame_duplicate_columns_size_mismatch(self):
455
+ # GH#39510
456
+ cols = ["A", "B", "C"] * 2
457
+ df = DataFrame(index=range(3), columns=cols)
458
+ with pytest.raises(ValueError, match="Columns must be same length as key"):
459
+ df[["A"]] = (0, 3, 5)
460
+
461
+ df2 = df.iloc[:, :3] # unique columns
462
+ with pytest.raises(ValueError, match="Columns must be same length as key"):
463
+ df2[["A"]] = (0, 3, 5)
464
+
465
+ @pytest.mark.parametrize("cols", [["a", "b", "c"], ["a", "a", "a"]])
466
+ def test_setitem_df_wrong_column_number(self, cols):
467
+ # GH#38604
468
+ df = DataFrame([[1, 2, 3]], columns=cols)
469
+ rhs = DataFrame([[10, 11]], columns=["d", "e"])
470
+ msg = "Columns must be same length as key"
471
+ with pytest.raises(ValueError, match=msg):
472
+ df["a"] = rhs
473
+
474
+ def test_setitem_listlike_indexer_duplicate_columns(self):
475
+ # GH#38604
476
+ df = DataFrame([[1, 2, 3]], columns=["a", "b", "b"])
477
+ rhs = DataFrame([[10, 11, 12]], columns=["a", "b", "b"])
478
+ df[["a", "b"]] = rhs
479
+ expected = DataFrame([[10, 11, 12]], columns=["a", "b", "b"])
480
+ tm.assert_frame_equal(df, expected)
481
+
482
+ df[["c", "b"]] = rhs
483
+ expected = DataFrame([[10, 11, 12, 10]], columns=["a", "b", "b", "c"])
484
+ tm.assert_frame_equal(df, expected)
485
+
486
+ def test_setitem_listlike_indexer_duplicate_columns_not_equal_length(self):
487
+ # GH#39403
488
+ df = DataFrame([[1, 2, 3]], columns=["a", "b", "b"])
489
+ rhs = DataFrame([[10, 11]], columns=["a", "b"])
490
+ msg = "Columns must be same length as key"
491
+ with pytest.raises(ValueError, match=msg):
492
+ df[["a", "b"]] = rhs
493
+
494
+ def test_setitem_intervals(self):
495
+ df = DataFrame({"A": range(10)})
496
+ ser = cut(df["A"], 5)
497
+ assert isinstance(ser.cat.categories, IntervalIndex)
498
+
499
+ # B & D end up as Categoricals
500
+ # the remainder are converted to in-line objects
501
+ # containing an IntervalIndex.values
502
+ df["B"] = ser
503
+ df["C"] = np.array(ser)
504
+ df["D"] = ser.values
505
+ df["E"] = np.array(ser.values)
506
+ df["F"] = ser.astype(object)
507
+
508
+ assert isinstance(df["B"].dtype, CategoricalDtype)
509
+ assert isinstance(df["B"].cat.categories.dtype, IntervalDtype)
510
+ assert isinstance(df["D"].dtype, CategoricalDtype)
511
+ assert isinstance(df["D"].cat.categories.dtype, IntervalDtype)
512
+
513
+ # These go through the Series constructor and so get inferred back
514
+ # to IntervalDtype
515
+ assert isinstance(df["C"].dtype, IntervalDtype)
516
+ assert isinstance(df["E"].dtype, IntervalDtype)
517
+
518
+ # But the Series constructor doesn't do inference on Series objects,
519
+ # so setting df["F"] doesn't get cast back to IntervalDtype
520
+ assert is_object_dtype(df["F"])
521
+
522
+ # they compare equal as Index
523
+ # when converted to numpy objects
524
+ c = lambda x: Index(np.array(x))
525
+ tm.assert_index_equal(c(df.B), c(df.B))
526
+ tm.assert_index_equal(c(df.B), c(df.C), check_names=False)
527
+ tm.assert_index_equal(c(df.B), c(df.D), check_names=False)
528
+ tm.assert_index_equal(c(df.C), c(df.D), check_names=False)
529
+
530
+ # B & D are the same Series
531
+ tm.assert_series_equal(df["B"], df["B"])
532
+ tm.assert_series_equal(df["B"], df["D"], check_names=False)
533
+
534
+ # C & E are the same Series
535
+ tm.assert_series_equal(df["C"], df["C"])
536
+ tm.assert_series_equal(df["C"], df["E"], check_names=False)
537
+
538
+ def test_setitem_categorical(self):
539
+ # GH#35369
540
+ df = DataFrame({"h": Series(list("mn")).astype("category")})
541
+ df.h = df.h.cat.reorder_categories(["n", "m"])
542
+ expected = DataFrame(
543
+ {"h": Categorical(["m", "n"]).reorder_categories(["n", "m"])}
544
+ )
545
+ tm.assert_frame_equal(df, expected)
546
+
547
+ def test_setitem_with_empty_listlike(self):
548
+ # GH#17101
549
+ index = Index([], name="idx")
550
+ result = DataFrame(columns=["A"], index=index)
551
+ result["A"] = []
552
+ expected = DataFrame(columns=["A"], index=index)
553
+ tm.assert_index_equal(result.index, expected.index)
554
+
555
+ @pytest.mark.parametrize(
556
+ "cols, values, expected",
557
+ [
558
+ (["C", "D", "D", "a"], [1, 2, 3, 4], 4), # with duplicates
559
+ (["D", "C", "D", "a"], [1, 2, 3, 4], 4), # mixed order
560
+ (["C", "B", "B", "a"], [1, 2, 3, 4], 4), # other duplicate cols
561
+ (["C", "B", "a"], [1, 2, 3], 3), # no duplicates
562
+ (["B", "C", "a"], [3, 2, 1], 1), # alphabetical order
563
+ (["C", "a", "B"], [3, 2, 1], 2), # in the middle
564
+ ],
565
+ )
566
+ def test_setitem_same_column(self, cols, values, expected):
567
+ # GH#23239
568
+ df = DataFrame([values], columns=cols)
569
+ df["a"] = df["a"]
570
+ result = df["a"].values[0]
571
+ assert result == expected
572
+
573
+ def test_setitem_multi_index(self):
574
+ # GH#7655, test that assigning to a sub-frame of a frame
575
+ # with multi-index columns aligns both rows and columns
576
+ it = ["jim", "joe", "jolie"], ["first", "last"], ["left", "center", "right"]
577
+
578
+ cols = MultiIndex.from_product(it)
579
+ index = date_range("20141006", periods=20)
580
+ vals = np.random.default_rng(2).integers(1, 1000, (len(index), len(cols)))
581
+ df = DataFrame(vals, columns=cols, index=index)
582
+
583
+ i, j = df.index.values.copy(), it[-1][:]
584
+
585
+ np.random.default_rng(2).shuffle(i)
586
+ df["jim"] = df["jolie"].loc[i, ::-1]
587
+ tm.assert_frame_equal(df["jim"], df["jolie"])
588
+
589
+ np.random.default_rng(2).shuffle(j)
590
+ df[("joe", "first")] = df[("jolie", "last")].loc[i, j]
591
+ tm.assert_frame_equal(df[("joe", "first")], df[("jolie", "last")])
592
+
593
+ np.random.default_rng(2).shuffle(j)
594
+ df[("joe", "last")] = df[("jolie", "first")].loc[i, j]
595
+ tm.assert_frame_equal(df[("joe", "last")], df[("jolie", "first")])
596
+
597
+ @pytest.mark.parametrize(
598
+ "columns,box,expected",
599
+ [
600
+ (
601
+ ["A", "B", "C", "D"],
602
+ 7,
603
+ DataFrame(
604
+ [[7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7]],
605
+ columns=["A", "B", "C", "D"],
606
+ ),
607
+ ),
608
+ (
609
+ ["C", "D"],
610
+ [7, 8],
611
+ DataFrame(
612
+ [[1, 2, 7, 8], [3, 4, 7, 8], [5, 6, 7, 8]],
613
+ columns=["A", "B", "C", "D"],
614
+ ),
615
+ ),
616
+ (
617
+ ["A", "B", "C"],
618
+ np.array([7, 8, 9], dtype=np.int64),
619
+ DataFrame([[7, 8, 9], [7, 8, 9], [7, 8, 9]], columns=["A", "B", "C"]),
620
+ ),
621
+ (
622
+ ["B", "C", "D"],
623
+ [[7, 8, 9], [10, 11, 12], [13, 14, 15]],
624
+ DataFrame(
625
+ [[1, 7, 8, 9], [3, 10, 11, 12], [5, 13, 14, 15]],
626
+ columns=["A", "B", "C", "D"],
627
+ ),
628
+ ),
629
+ (
630
+ ["C", "A", "D"],
631
+ np.array([[7, 8, 9], [10, 11, 12], [13, 14, 15]], dtype=np.int64),
632
+ DataFrame(
633
+ [[8, 2, 7, 9], [11, 4, 10, 12], [14, 6, 13, 15]],
634
+ columns=["A", "B", "C", "D"],
635
+ ),
636
+ ),
637
+ (
638
+ ["A", "C"],
639
+ DataFrame([[7, 8], [9, 10], [11, 12]], columns=["A", "C"]),
640
+ DataFrame(
641
+ [[7, 2, 8], [9, 4, 10], [11, 6, 12]], columns=["A", "B", "C"]
642
+ ),
643
+ ),
644
+ ],
645
+ )
646
+ def test_setitem_list_missing_columns(self, columns, box, expected):
647
+ # GH#29334
648
+ df = DataFrame([[1, 2], [3, 4], [5, 6]], columns=["A", "B"])
649
+ df[columns] = box
650
+ tm.assert_frame_equal(df, expected)
651
+
652
+ def test_setitem_list_of_tuples(self, float_frame):
653
+ tuples = list(zip(float_frame["A"], float_frame["B"]))
654
+ float_frame["tuples"] = tuples
655
+
656
+ result = float_frame["tuples"]
657
+ expected = Series(tuples, index=float_frame.index, name="tuples")
658
+ tm.assert_series_equal(result, expected)
659
+
660
+ def test_setitem_iloc_generator(self):
661
+ # GH#39614
662
+ df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
663
+ indexer = (x for x in [1, 2])
664
+ df.iloc[indexer] = 1
665
+ expected = DataFrame({"a": [1, 1, 1], "b": [4, 1, 1]})
666
+ tm.assert_frame_equal(df, expected)
667
+
668
+ def test_setitem_iloc_two_dimensional_generator(self):
669
+ df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
670
+ indexer = (x for x in [1, 2])
671
+ df.iloc[indexer, 1] = 1
672
+ expected = DataFrame({"a": [1, 2, 3], "b": [4, 1, 1]})
673
+ tm.assert_frame_equal(df, expected)
674
+
675
+ def test_setitem_dtypes_bytes_type_to_object(self):
676
+ # GH 20734
677
+ index = Series(name="id", dtype="S24")
678
+ df = DataFrame(index=index)
679
+ df["a"] = Series(name="a", index=index, dtype=np.uint32)
680
+ df["b"] = Series(name="b", index=index, dtype="S64")
681
+ df["c"] = Series(name="c", index=index, dtype="S64")
682
+ df["d"] = Series(name="d", index=index, dtype=np.uint8)
683
+ result = df.dtypes
684
+ expected = Series([np.uint32, object, object, np.uint8], index=list("abcd"))
685
+ tm.assert_series_equal(result, expected)
686
+
687
+ def test_boolean_mask_nullable_int64(self):
688
+ # GH 28928
689
+ result = DataFrame({"a": [3, 4], "b": [5, 6]}).astype(
690
+ {"a": "int64", "b": "Int64"}
691
+ )
692
+ mask = Series(False, index=result.index)
693
+ result.loc[mask, "a"] = result["a"]
694
+ result.loc[mask, "b"] = result["b"]
695
+ expected = DataFrame({"a": [3, 4], "b": [5, 6]}).astype(
696
+ {"a": "int64", "b": "Int64"}
697
+ )
698
+ tm.assert_frame_equal(result, expected)
699
+
700
+ def test_setitem_ea_dtype_rhs_series(self):
701
+ # GH#47425
702
+ df = DataFrame({"a": [1, 2]})
703
+ df["a"] = Series([1, 2], dtype="Int64")
704
+ expected = DataFrame({"a": [1, 2]}, dtype="Int64")
705
+ tm.assert_frame_equal(df, expected)
706
+
707
+ # TODO(ArrayManager) set column with 2d column array, see #44788
708
+ @td.skip_array_manager_not_yet_implemented
709
+ def test_setitem_npmatrix_2d(self):
710
+ # GH#42376
711
+ # for use-case df["x"] = sparse.random((10, 10)).mean(axis=1)
712
+ expected = DataFrame(
713
+ {"np-array": np.ones(10), "np-matrix": np.ones(10)}, index=np.arange(10)
714
+ )
715
+
716
+ a = np.ones((10, 1))
717
+ df = DataFrame(index=np.arange(10))
718
+ df["np-array"] = a
719
+
720
+ # Instantiation of `np.matrix` gives PendingDeprecationWarning
721
+ with tm.assert_produces_warning(PendingDeprecationWarning):
722
+ df["np-matrix"] = np.matrix(a)
723
+
724
+ tm.assert_frame_equal(df, expected)
725
+
726
+ @pytest.mark.parametrize("vals", [{}, {"d": "a"}])
727
+ def test_setitem_aligning_dict_with_index(self, vals):
728
+ # GH#47216
729
+ df = DataFrame({"a": [1, 2], "b": [3, 4], **vals})
730
+ df.loc[:, "a"] = {1: 100, 0: 200}
731
+ df.loc[:, "c"] = {0: 5, 1: 6}
732
+ df.loc[:, "e"] = {1: 5}
733
+ expected = DataFrame(
734
+ {"a": [200, 100], "b": [3, 4], **vals, "c": [5, 6], "e": [np.nan, 5]}
735
+ )
736
+ tm.assert_frame_equal(df, expected)
737
+
738
+ def test_setitem_rhs_dataframe(self):
739
+ # GH#47578
740
+ df = DataFrame({"a": [1, 2]})
741
+ df["a"] = DataFrame({"a": [10, 11]}, index=[1, 2])
742
+ expected = DataFrame({"a": [np.nan, 10]})
743
+ tm.assert_frame_equal(df, expected)
744
+
745
+ df = DataFrame({"a": [1, 2]})
746
+ df.isetitem(0, DataFrame({"a": [10, 11]}, index=[1, 2]))
747
+ tm.assert_frame_equal(df, expected)
748
+
749
+ def test_setitem_frame_overwrite_with_ea_dtype(self, any_numeric_ea_dtype):
750
+ # GH#46896
751
+ df = DataFrame(columns=["a", "b"], data=[[1, 2], [3, 4]])
752
+ df["a"] = DataFrame({"a": [10, 11]}, dtype=any_numeric_ea_dtype)
753
+ expected = DataFrame(
754
+ {
755
+ "a": Series([10, 11], dtype=any_numeric_ea_dtype),
756
+ "b": [2, 4],
757
+ }
758
+ )
759
+ tm.assert_frame_equal(df, expected)
760
+
761
+ def test_setitem_string_option_object_index(self):
762
+ # GH#55638
763
+ pytest.importorskip("pyarrow")
764
+ df = DataFrame({"a": [1, 2]})
765
+ with pd.option_context("future.infer_string", True):
766
+ df["b"] = Index(["a", "b"], dtype=object)
767
+ expected = DataFrame({"a": [1, 2], "b": Series(["a", "b"], dtype=object)})
768
+ tm.assert_frame_equal(df, expected)
769
+
770
+ def test_setitem_frame_midx_columns(self):
771
+ # GH#49121
772
+ df = DataFrame({("a", "b"): [10]})
773
+ expected = df.copy()
774
+ col_name = ("a", "b")
775
+ df[col_name] = df[[col_name]]
776
+ tm.assert_frame_equal(df, expected)
777
+
778
+ def test_loc_setitem_ea_dtype(self):
779
+ # GH#55604
780
+ df = DataFrame({"a": np.array([10], dtype="i8")})
781
+ df.loc[:, "a"] = Series([11], dtype="Int64")
782
+ expected = DataFrame({"a": np.array([11], dtype="i8")})
783
+ tm.assert_frame_equal(df, expected)
784
+
785
+ df = DataFrame({"a": np.array([10], dtype="i8")})
786
+ df.iloc[:, 0] = Series([11], dtype="Int64")
787
+ tm.assert_frame_equal(df, expected)
788
+
789
+ def test_setitem_object_inferring(self):
790
+ # GH#56102
791
+ idx = Index([Timestamp("2019-12-31")], dtype=object)
792
+ df = DataFrame({"a": [1]})
793
+ with tm.assert_produces_warning(FutureWarning, match="infer"):
794
+ df.loc[:, "b"] = idx
795
+ with tm.assert_produces_warning(FutureWarning, match="infer"):
796
+ df["c"] = idx
797
+
798
+ expected = DataFrame(
799
+ {
800
+ "a": [1],
801
+ "b": Series([Timestamp("2019-12-31")], dtype="datetime64[ns]"),
802
+ "c": Series([Timestamp("2019-12-31")], dtype="datetime64[ns]"),
803
+ }
804
+ )
805
+ tm.assert_frame_equal(df, expected)
806
+
807
+
808
+ class TestSetitemTZAwareValues:
809
+ @pytest.fixture
810
+ def idx(self):
811
+ naive = DatetimeIndex(["2013-1-1 13:00", "2013-1-2 14:00"], name="B")
812
+ idx = naive.tz_localize("US/Pacific")
813
+ return idx
814
+
815
+ @pytest.fixture
816
+ def expected(self, idx):
817
+ expected = Series(np.array(idx.tolist(), dtype="object"), name="B")
818
+ assert expected.dtype == idx.dtype
819
+ return expected
820
+
821
+ def test_setitem_dt64series(self, idx, expected):
822
+ # convert to utc
823
+ df = DataFrame(np.random.default_rng(2).standard_normal((2, 1)), columns=["A"])
824
+ df["B"] = idx
825
+ df["B"] = idx.to_series(index=[0, 1]).dt.tz_convert(None)
826
+
827
+ result = df["B"]
828
+ comp = Series(idx.tz_convert("UTC").tz_localize(None), name="B")
829
+ tm.assert_series_equal(result, comp)
830
+
831
+ def test_setitem_datetimeindex(self, idx, expected):
832
+ # setting a DataFrame column with a tzaware DTI retains the dtype
833
+ df = DataFrame(np.random.default_rng(2).standard_normal((2, 1)), columns=["A"])
834
+
835
+ # assign to frame
836
+ df["B"] = idx
837
+ result = df["B"]
838
+ tm.assert_series_equal(result, expected)
839
+
840
+ def test_setitem_object_array_of_tzaware_datetimes(self, idx, expected):
841
+ # setting a DataFrame column with a tzaware DTI retains the dtype
842
+ df = DataFrame(np.random.default_rng(2).standard_normal((2, 1)), columns=["A"])
843
+
844
+ # object array of datetimes with a tz
845
+ df["B"] = idx.to_pydatetime()
846
+ result = df["B"]
847
+ tm.assert_series_equal(result, expected)
848
+
849
+
850
+ class TestDataFrameSetItemWithExpansion:
851
+ def test_setitem_listlike_views(self, using_copy_on_write, warn_copy_on_write):
852
+ # GH#38148
853
+ df = DataFrame({"a": [1, 2, 3], "b": [4, 4, 6]})
854
+
855
+ # get one column as a view of df
856
+ ser = df["a"]
857
+
858
+ # add columns with list-like indexer
859
+ df[["c", "d"]] = np.array([[0.1, 0.2], [0.3, 0.4], [0.4, 0.5]])
860
+
861
+ # edit in place the first column to check view semantics
862
+ with tm.assert_cow_warning(warn_copy_on_write):
863
+ df.iloc[0, 0] = 100
864
+
865
+ if using_copy_on_write:
866
+ expected = Series([1, 2, 3], name="a")
867
+ else:
868
+ expected = Series([100, 2, 3], name="a")
869
+ tm.assert_series_equal(ser, expected)
870
+
871
+ def test_setitem_string_column_numpy_dtype_raising(self):
872
+ # GH#39010
873
+ df = DataFrame([[1, 2], [3, 4]])
874
+ df["0 - Name"] = [5, 6]
875
+ expected = DataFrame([[1, 2, 5], [3, 4, 6]], columns=[0, 1, "0 - Name"])
876
+ tm.assert_frame_equal(df, expected)
877
+
878
+ def test_setitem_empty_df_duplicate_columns(self, using_copy_on_write):
879
+ # GH#38521
880
+ df = DataFrame(columns=["a", "b", "b"], dtype="float64")
881
+ df.loc[:, "a"] = list(range(2))
882
+ expected = DataFrame(
883
+ [[0, np.nan, np.nan], [1, np.nan, np.nan]], columns=["a", "b", "b"]
884
+ )
885
+ tm.assert_frame_equal(df, expected)
886
+
887
+ def test_setitem_with_expansion_categorical_dtype(self):
888
+ # assignment
889
+ df = DataFrame(
890
+ {
891
+ "value": np.array(
892
+ np.random.default_rng(2).integers(0, 10000, 100), dtype="int32"
893
+ )
894
+ }
895
+ )
896
+ labels = Categorical([f"{i} - {i + 499}" for i in range(0, 10000, 500)])
897
+
898
+ df = df.sort_values(by=["value"], ascending=True)
899
+ ser = cut(df.value, range(0, 10500, 500), right=False, labels=labels)
900
+ cat = ser.values
901
+
902
+ # setting with a Categorical
903
+ df["D"] = cat
904
+ result = df.dtypes
905
+ expected = Series(
906
+ [np.dtype("int32"), CategoricalDtype(categories=labels, ordered=False)],
907
+ index=["value", "D"],
908
+ )
909
+ tm.assert_series_equal(result, expected)
910
+
911
+ # setting with a Series
912
+ df["E"] = ser
913
+ result = df.dtypes
914
+ expected = Series(
915
+ [
916
+ np.dtype("int32"),
917
+ CategoricalDtype(categories=labels, ordered=False),
918
+ CategoricalDtype(categories=labels, ordered=False),
919
+ ],
920
+ index=["value", "D", "E"],
921
+ )
922
+ tm.assert_series_equal(result, expected)
923
+
924
+ result1 = df["D"]
925
+ result2 = df["E"]
926
+ tm.assert_categorical_equal(result1._mgr.array, cat)
927
+
928
+ # sorting
929
+ ser.name = "E"
930
+ tm.assert_series_equal(result2.sort_index(), ser.sort_index())
931
+
932
+ def test_setitem_scalars_no_index(self):
933
+ # GH#16823 / GH#17894
934
+ df = DataFrame()
935
+ df["foo"] = 1
936
+ expected = DataFrame(columns=["foo"]).astype(np.int64)
937
+ tm.assert_frame_equal(df, expected)
938
+
939
+ def test_setitem_newcol_tuple_key(self, float_frame):
940
+ assert (
941
+ "A",
942
+ "B",
943
+ ) not in float_frame.columns
944
+ float_frame["A", "B"] = float_frame["A"]
945
+ assert ("A", "B") in float_frame.columns
946
+
947
+ result = float_frame["A", "B"]
948
+ expected = float_frame["A"]
949
+ tm.assert_series_equal(result, expected, check_names=False)
950
+
951
+ def test_frame_setitem_newcol_timestamp(self):
952
+ # GH#2155
953
+ columns = date_range(start="1/1/2012", end="2/1/2012", freq=BDay())
954
+ data = DataFrame(columns=columns, index=range(10))
955
+ t = datetime(2012, 11, 1)
956
+ ts = Timestamp(t)
957
+ data[ts] = np.nan # works, mostly a smoke-test
958
+ assert np.isnan(data[ts]).all()
959
+
960
+ def test_frame_setitem_rangeindex_into_new_col(self):
961
+ # GH#47128
962
+ df = DataFrame({"a": ["a", "b"]})
963
+ df["b"] = df.index
964
+ df.loc[[False, True], "b"] = 100
965
+ result = df.loc[[1], :]
966
+ expected = DataFrame({"a": ["b"], "b": [100]}, index=[1])
967
+ tm.assert_frame_equal(result, expected)
968
+
969
+ def test_setitem_frame_keep_ea_dtype(self, any_numeric_ea_dtype):
970
+ # GH#46896
971
+ df = DataFrame(columns=["a", "b"], data=[[1, 2], [3, 4]])
972
+ df["c"] = DataFrame({"a": [10, 11]}, dtype=any_numeric_ea_dtype)
973
+ expected = DataFrame(
974
+ {
975
+ "a": [1, 3],
976
+ "b": [2, 4],
977
+ "c": Series([10, 11], dtype=any_numeric_ea_dtype),
978
+ }
979
+ )
980
+ tm.assert_frame_equal(df, expected)
981
+
982
+ def test_loc_expansion_with_timedelta_type(self):
983
+ result = DataFrame(columns=list("abc"))
984
+ result.loc[0] = {
985
+ "a": pd.to_timedelta(5, unit="s"),
986
+ "b": pd.to_timedelta(72, unit="s"),
987
+ "c": "23",
988
+ }
989
+ expected = DataFrame(
990
+ [[pd.Timedelta("0 days 00:00:05"), pd.Timedelta("0 days 00:01:12"), "23"]],
991
+ index=Index([0]),
992
+ columns=(["a", "b", "c"]),
993
+ )
994
+ tm.assert_frame_equal(result, expected)
995
+
996
+
997
+ class TestDataFrameSetItemSlicing:
998
+ def test_setitem_slice_position(self):
999
+ # GH#31469
1000
+ df = DataFrame(np.zeros((100, 1)))
1001
+ df[-4:] = 1
1002
+ arr = np.zeros((100, 1))
1003
+ arr[-4:] = 1
1004
+ expected = DataFrame(arr)
1005
+ tm.assert_frame_equal(df, expected)
1006
+
1007
+ @pytest.mark.parametrize("indexer", [tm.setitem, tm.iloc])
1008
+ @pytest.mark.parametrize("box", [Series, np.array, list, pd.array])
1009
+ @pytest.mark.parametrize("n", [1, 2, 3])
1010
+ def test_setitem_slice_indexer_broadcasting_rhs(self, n, box, indexer):
1011
+ # GH#40440
1012
+ df = DataFrame([[1, 3, 5]] + [[2, 4, 6]] * n, columns=["a", "b", "c"])
1013
+ indexer(df)[1:] = box([10, 11, 12])
1014
+ expected = DataFrame([[1, 3, 5]] + [[10, 11, 12]] * n, columns=["a", "b", "c"])
1015
+ tm.assert_frame_equal(df, expected)
1016
+
1017
+ @pytest.mark.parametrize("box", [Series, np.array, list, pd.array])
1018
+ @pytest.mark.parametrize("n", [1, 2, 3])
1019
+ def test_setitem_list_indexer_broadcasting_rhs(self, n, box):
1020
+ # GH#40440
1021
+ df = DataFrame([[1, 3, 5]] + [[2, 4, 6]] * n, columns=["a", "b", "c"])
1022
+ df.iloc[list(range(1, n + 1))] = box([10, 11, 12])
1023
+ expected = DataFrame([[1, 3, 5]] + [[10, 11, 12]] * n, columns=["a", "b", "c"])
1024
+ tm.assert_frame_equal(df, expected)
1025
+
1026
+ @pytest.mark.parametrize("indexer", [tm.setitem, tm.iloc])
1027
+ @pytest.mark.parametrize("box", [Series, np.array, list, pd.array])
1028
+ @pytest.mark.parametrize("n", [1, 2, 3])
1029
+ def test_setitem_slice_broadcasting_rhs_mixed_dtypes(self, n, box, indexer):
1030
+ # GH#40440
1031
+ df = DataFrame(
1032
+ [[1, 3, 5], ["x", "y", "z"]] + [[2, 4, 6]] * n, columns=["a", "b", "c"]
1033
+ )
1034
+ indexer(df)[1:] = box([10, 11, 12])
1035
+ expected = DataFrame(
1036
+ [[1, 3, 5]] + [[10, 11, 12]] * (n + 1),
1037
+ columns=["a", "b", "c"],
1038
+ dtype="object",
1039
+ )
1040
+ tm.assert_frame_equal(df, expected)
1041
+
1042
+
1043
+ class TestDataFrameSetItemCallable:
1044
+ def test_setitem_callable(self):
1045
+ # GH#12533
1046
+ df = DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8]})
1047
+ df[lambda x: "A"] = [11, 12, 13, 14]
1048
+
1049
+ exp = DataFrame({"A": [11, 12, 13, 14], "B": [5, 6, 7, 8]})
1050
+ tm.assert_frame_equal(df, exp)
1051
+
1052
+ def test_setitem_other_callable(self):
1053
+ # GH#13299
1054
+ def inc(x):
1055
+ return x + 1
1056
+
1057
+ # Set dtype object straight away to avoid upcast when setting inc below
1058
+ df = DataFrame([[-1, 1], [1, -1]], dtype=object)
1059
+ df[df > 0] = inc
1060
+
1061
+ expected = DataFrame([[-1, inc], [inc, -1]])
1062
+ tm.assert_frame_equal(df, expected)
1063
+
1064
+
1065
+ class TestDataFrameSetItemBooleanMask:
1066
+ @td.skip_array_manager_invalid_test # TODO(ArrayManager) rewrite not using .values
1067
+ @pytest.mark.parametrize(
1068
+ "mask_type",
1069
+ [lambda df: df > np.abs(df) / 2, lambda df: (df > np.abs(df) / 2).values],
1070
+ ids=["dataframe", "array"],
1071
+ )
1072
+ def test_setitem_boolean_mask(self, mask_type, float_frame):
1073
+ # Test for issue #18582
1074
+ df = float_frame.copy()
1075
+ mask = mask_type(df)
1076
+
1077
+ # index with boolean mask
1078
+ result = df.copy()
1079
+ result[mask] = np.nan
1080
+
1081
+ expected = df.values.copy()
1082
+ expected[np.array(mask)] = np.nan
1083
+ expected = DataFrame(expected, index=df.index, columns=df.columns)
1084
+ tm.assert_frame_equal(result, expected)
1085
+
1086
+ @pytest.mark.xfail(reason="Currently empty indexers are treated as all False")
1087
+ @pytest.mark.parametrize("box", [list, np.array, Series])
1088
+ def test_setitem_loc_empty_indexer_raises_with_non_empty_value(self, box):
1089
+ # GH#37672
1090
+ df = DataFrame({"a": ["a"], "b": [1], "c": [1]})
1091
+ if box == Series:
1092
+ indexer = box([], dtype="object")
1093
+ else:
1094
+ indexer = box([])
1095
+ msg = "Must have equal len keys and value when setting with an iterable"
1096
+ with pytest.raises(ValueError, match=msg):
1097
+ df.loc[indexer, ["b"]] = [1]
1098
+
1099
+ @pytest.mark.parametrize("box", [list, np.array, Series])
1100
+ def test_setitem_loc_only_false_indexer_dtype_changed(self, box):
1101
+ # GH#37550
1102
+ # Dtype is only changed when value to set is a Series and indexer is
1103
+ # empty/bool all False
1104
+ df = DataFrame({"a": ["a"], "b": [1], "c": [1]})
1105
+ indexer = box([False])
1106
+ df.loc[indexer, ["b"]] = 10 - df["c"]
1107
+ expected = DataFrame({"a": ["a"], "b": [1], "c": [1]})
1108
+ tm.assert_frame_equal(df, expected)
1109
+
1110
+ df.loc[indexer, ["b"]] = 9
1111
+ tm.assert_frame_equal(df, expected)
1112
+
1113
+ @pytest.mark.parametrize("indexer", [tm.setitem, tm.loc])
1114
+ def test_setitem_boolean_mask_aligning(self, indexer):
1115
+ # GH#39931
1116
+ df = DataFrame({"a": [1, 4, 2, 3], "b": [5, 6, 7, 8]})
1117
+ expected = df.copy()
1118
+ mask = df["a"] >= 3
1119
+ indexer(df)[mask] = indexer(df)[mask].sort_values("a")
1120
+ tm.assert_frame_equal(df, expected)
1121
+
1122
+ def test_setitem_mask_categorical(self):
1123
+ # assign multiple rows (mixed values) (-> array) -> exp_multi_row
1124
+ # changed multiple rows
1125
+ cats2 = Categorical(["a", "a", "b", "b", "a", "a", "a"], categories=["a", "b"])
1126
+ idx2 = Index(["h", "i", "j", "k", "l", "m", "n"])
1127
+ values2 = [1, 1, 2, 2, 1, 1, 1]
1128
+ exp_multi_row = DataFrame({"cats": cats2, "values": values2}, index=idx2)
1129
+
1130
+ catsf = Categorical(
1131
+ ["a", "a", "c", "c", "a", "a", "a"], categories=["a", "b", "c"]
1132
+ )
1133
+ idxf = Index(["h", "i", "j", "k", "l", "m", "n"])
1134
+ valuesf = [1, 1, 3, 3, 1, 1, 1]
1135
+ df = DataFrame({"cats": catsf, "values": valuesf}, index=idxf)
1136
+
1137
+ exp_fancy = exp_multi_row.copy()
1138
+ exp_fancy["cats"] = exp_fancy["cats"].cat.set_categories(["a", "b", "c"])
1139
+
1140
+ mask = df["cats"] == "c"
1141
+ df[mask] = ["b", 2]
1142
+ # category c is kept in .categories
1143
+ tm.assert_frame_equal(df, exp_fancy)
1144
+
1145
+ @pytest.mark.parametrize("dtype", ["float", "int64"])
1146
+ @pytest.mark.parametrize("kwargs", [{}, {"index": [1]}, {"columns": ["A"]}])
1147
+ def test_setitem_empty_frame_with_boolean(self, dtype, kwargs):
1148
+ # see GH#10126
1149
+ kwargs["dtype"] = dtype
1150
+ df = DataFrame(**kwargs)
1151
+
1152
+ df2 = df.copy()
1153
+ df[df > df2] = 47
1154
+ tm.assert_frame_equal(df, df2)
1155
+
1156
+ def test_setitem_boolean_indexing(self):
1157
+ idx = list(range(3))
1158
+ cols = ["A", "B", "C"]
1159
+ df1 = DataFrame(
1160
+ index=idx,
1161
+ columns=cols,
1162
+ data=np.array(
1163
+ [[0.0, 0.5, 1.0], [1.5, 2.0, 2.5], [3.0, 3.5, 4.0]], dtype=float
1164
+ ),
1165
+ )
1166
+ df2 = DataFrame(index=idx, columns=cols, data=np.ones((len(idx), len(cols))))
1167
+
1168
+ expected = DataFrame(
1169
+ index=idx,
1170
+ columns=cols,
1171
+ data=np.array([[0.0, 0.5, 1.0], [1.5, 2.0, -1], [-1, -1, -1]], dtype=float),
1172
+ )
1173
+
1174
+ df1[df1 > 2.0 * df2] = -1
1175
+ tm.assert_frame_equal(df1, expected)
1176
+ with pytest.raises(ValueError, match="Item wrong length"):
1177
+ df1[df1.index[:-1] > 2] = -1
1178
+
1179
+ def test_loc_setitem_all_false_boolean_two_blocks(self):
1180
+ # GH#40885
1181
+ df = DataFrame({"a": [1, 2], "b": [3, 4], "c": "a"})
1182
+ expected = df.copy()
1183
+ indexer = Series([False, False], name="c")
1184
+ df.loc[indexer, ["b"]] = DataFrame({"b": [5, 6]}, index=[0, 1])
1185
+ tm.assert_frame_equal(df, expected)
1186
+
1187
+ def test_setitem_ea_boolean_mask(self):
1188
+ # GH#47125
1189
+ df = DataFrame([[-1, 2], [3, -4]])
1190
+ expected = DataFrame([[0, 2], [3, 0]])
1191
+ boolean_indexer = DataFrame(
1192
+ {
1193
+ 0: Series([True, False], dtype="boolean"),
1194
+ 1: Series([pd.NA, True], dtype="boolean"),
1195
+ }
1196
+ )
1197
+ df[boolean_indexer] = 0
1198
+ tm.assert_frame_equal(df, expected)
1199
+
1200
+
1201
+ class TestDataFrameSetitemCopyViewSemantics:
1202
+ def test_setitem_always_copy(self, float_frame):
1203
+ assert "E" not in float_frame.columns
1204
+ s = float_frame["A"].copy()
1205
+ float_frame["E"] = s
1206
+
1207
+ float_frame.iloc[5:10, float_frame.columns.get_loc("E")] = np.nan
1208
+ assert notna(s[5:10]).all()
1209
+
1210
+ @pytest.mark.parametrize("consolidate", [True, False])
1211
+ def test_setitem_partial_column_inplace(
1212
+ self, consolidate, using_array_manager, using_copy_on_write
1213
+ ):
1214
+ # This setting should be in-place, regardless of whether frame is
1215
+ # single-block or multi-block
1216
+ # GH#304 this used to be incorrectly not-inplace, in which case
1217
+ # we needed to ensure _item_cache was cleared.
1218
+
1219
+ df = DataFrame(
1220
+ {"x": [1.1, 2.1, 3.1, 4.1], "y": [5.1, 6.1, 7.1, 8.1]}, index=[0, 1, 2, 3]
1221
+ )
1222
+ df.insert(2, "z", np.nan)
1223
+ if not using_array_manager:
1224
+ if consolidate:
1225
+ df._consolidate_inplace()
1226
+ assert len(df._mgr.blocks) == 1
1227
+ else:
1228
+ assert len(df._mgr.blocks) == 2
1229
+
1230
+ zvals = df["z"]._values
1231
+
1232
+ df.loc[2:, "z"] = 42
1233
+
1234
+ expected = Series([np.nan, np.nan, 42, 42], index=df.index, name="z")
1235
+ tm.assert_series_equal(df["z"], expected)
1236
+
1237
+ # check setting occurred in-place
1238
+ if not using_copy_on_write:
1239
+ tm.assert_numpy_array_equal(zvals, expected.values)
1240
+ assert np.shares_memory(zvals, df["z"]._values)
1241
+
1242
+ def test_setitem_duplicate_columns_not_inplace(self):
1243
+ # GH#39510
1244
+ cols = ["A", "B"] * 2
1245
+ df = DataFrame(0.0, index=[0], columns=cols)
1246
+ df_copy = df.copy()
1247
+ df_view = df[:]
1248
+ df["B"] = (2, 5)
1249
+
1250
+ expected = DataFrame([[0.0, 2, 0.0, 5]], columns=cols)
1251
+ tm.assert_frame_equal(df_view, df_copy)
1252
+ tm.assert_frame_equal(df, expected)
1253
+
1254
+ @pytest.mark.parametrize(
1255
+ "value", [1, np.array([[1], [1]], dtype="int64"), [[1], [1]]]
1256
+ )
1257
+ def test_setitem_same_dtype_not_inplace(self, value, using_array_manager):
1258
+ # GH#39510
1259
+ cols = ["A", "B"]
1260
+ df = DataFrame(0, index=[0, 1], columns=cols)
1261
+ df_copy = df.copy()
1262
+ df_view = df[:]
1263
+ df[["B"]] = value
1264
+
1265
+ expected = DataFrame([[0, 1], [0, 1]], columns=cols)
1266
+ tm.assert_frame_equal(df, expected)
1267
+ tm.assert_frame_equal(df_view, df_copy)
1268
+
1269
+ @pytest.mark.parametrize("value", [1.0, np.array([[1.0], [1.0]]), [[1.0], [1.0]]])
1270
+ def test_setitem_listlike_key_scalar_value_not_inplace(self, value):
1271
+ # GH#39510
1272
+ cols = ["A", "B"]
1273
+ df = DataFrame(0, index=[0, 1], columns=cols)
1274
+ df_copy = df.copy()
1275
+ df_view = df[:]
1276
+ df[["B"]] = value
1277
+
1278
+ expected = DataFrame([[0, 1.0], [0, 1.0]], columns=cols)
1279
+ tm.assert_frame_equal(df_view, df_copy)
1280
+ tm.assert_frame_equal(df, expected)
1281
+
1282
+ @pytest.mark.parametrize(
1283
+ "indexer",
1284
+ [
1285
+ "a",
1286
+ ["a"],
1287
+ pytest.param(
1288
+ [True, False],
1289
+ marks=pytest.mark.xfail(
1290
+ reason="Boolean indexer incorrectly setting inplace",
1291
+ strict=False, # passing on some builds, no obvious pattern
1292
+ ),
1293
+ ),
1294
+ ],
1295
+ )
1296
+ @pytest.mark.parametrize(
1297
+ "value, set_value",
1298
+ [
1299
+ (1, 5),
1300
+ (1.0, 5.0),
1301
+ (Timestamp("2020-12-31"), Timestamp("2021-12-31")),
1302
+ ("a", "b"),
1303
+ ],
1304
+ )
1305
+ def test_setitem_not_operating_inplace(self, value, set_value, indexer):
1306
+ # GH#43406
1307
+ df = DataFrame({"a": value}, index=[0, 1])
1308
+ expected = df.copy()
1309
+ view = df[:]
1310
+ df[indexer] = set_value
1311
+ tm.assert_frame_equal(view, expected)
1312
+
1313
+ @td.skip_array_manager_invalid_test
1314
+ def test_setitem_column_update_inplace(
1315
+ self, using_copy_on_write, warn_copy_on_write
1316
+ ):
1317
+ # https://github.com/pandas-dev/pandas/issues/47172
1318
+
1319
+ labels = [f"c{i}" for i in range(10)]
1320
+ df = DataFrame({col: np.zeros(len(labels)) for col in labels}, index=labels)
1321
+ values = df._mgr.blocks[0].values
1322
+
1323
+ with tm.raises_chained_assignment_error():
1324
+ for label in df.columns:
1325
+ df[label][label] = 1
1326
+ if not using_copy_on_write:
1327
+ # diagonal values all updated
1328
+ assert np.all(values[np.arange(10), np.arange(10)] == 1)
1329
+ else:
1330
+ # original dataframe not updated
1331
+ assert np.all(values[np.arange(10), np.arange(10)] == 0)
1332
+
1333
+ def test_setitem_column_frame_as_category(self):
1334
+ # GH31581
1335
+ df = DataFrame([1, 2, 3])
1336
+ df["col1"] = DataFrame([1, 2, 3], dtype="category")
1337
+ df["col2"] = Series([1, 2, 3], dtype="category")
1338
+
1339
+ expected_types = Series(
1340
+ ["int64", "category", "category"], index=[0, "col1", "col2"], dtype=object
1341
+ )
1342
+ tm.assert_series_equal(df.dtypes, expected_types)
1343
+
1344
+ @pytest.mark.parametrize("dtype", ["int64", "Int64"])
1345
+ def test_setitem_iloc_with_numpy_array(self, dtype):
1346
+ # GH-33828
1347
+ df = DataFrame({"a": np.ones(3)}, dtype=dtype)
1348
+ df.iloc[np.array([0]), np.array([0])] = np.array([[2]])
1349
+
1350
+ expected = DataFrame({"a": [2, 1, 1]}, dtype=dtype)
1351
+ tm.assert_frame_equal(df, expected)
1352
+
1353
+ def test_setitem_frame_dup_cols_dtype(self):
1354
+ # GH#53143
1355
+ df = DataFrame([[1, 2, 3, 4], [4, 5, 6, 7]], columns=["a", "b", "a", "c"])
1356
+ rhs = DataFrame([[0, 1.5], [2, 2.5]], columns=["a", "a"])
1357
+ df["a"] = rhs
1358
+ expected = DataFrame(
1359
+ [[0, 2, 1.5, 4], [2, 5, 2.5, 7]], columns=["a", "b", "a", "c"]
1360
+ )
1361
+ tm.assert_frame_equal(df, expected)
1362
+
1363
+ df = DataFrame([[1, 2, 3], [4, 5, 6]], columns=["a", "a", "b"])
1364
+ rhs = DataFrame([[0, 1.5], [2, 2.5]], columns=["a", "a"])
1365
+ df["a"] = rhs
1366
+ expected = DataFrame([[0, 1.5, 3], [2, 2.5, 6]], columns=["a", "a", "b"])
1367
+ tm.assert_frame_equal(df, expected)
1368
+
1369
+ def test_frame_setitem_empty_dataframe(self):
1370
+ # GH#28871
1371
+ dti = DatetimeIndex(["2000-01-01"], dtype="M8[ns]", name="date")
1372
+ df = DataFrame({"date": dti}).set_index("date")
1373
+ df = df[0:0].copy()
1374
+
1375
+ df["3010"] = None
1376
+ df["2010"] = None
1377
+
1378
+ expected = DataFrame(
1379
+ [],
1380
+ columns=["3010", "2010"],
1381
+ index=dti[:0],
1382
+ )
1383
+ tm.assert_frame_equal(df, expected)
1384
+
1385
+
1386
+ def test_full_setter_loc_incompatible_dtype():
1387
+ # https://github.com/pandas-dev/pandas/issues/55791
1388
+ df = DataFrame({"a": [1, 2]})
1389
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
1390
+ df.loc[:, "a"] = True
1391
+ expected = DataFrame({"a": [True, True]})
1392
+ tm.assert_frame_equal(df, expected)
1393
+
1394
+ df = DataFrame({"a": [1, 2]})
1395
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
1396
+ df.loc[:, "a"] = {0: 3.5, 1: 4.5}
1397
+ expected = DataFrame({"a": [3.5, 4.5]})
1398
+ tm.assert_frame_equal(df, expected)
1399
+
1400
+ df = DataFrame({"a": [1, 2]})
1401
+ df.loc[:, "a"] = {0: 3, 1: 4}
1402
+ expected = DataFrame({"a": [3, 4]})
1403
+ tm.assert_frame_equal(df, expected)
1404
+
1405
+
1406
+ def test_setitem_partial_row_multiple_columns():
1407
+ # https://github.com/pandas-dev/pandas/issues/56503
1408
+ df = DataFrame({"A": [1, 2, 3], "B": [4.0, 5, 6]})
1409
+ # should not warn
1410
+ df.loc[df.index <= 1, ["F", "G"]] = (1, "abc")
1411
+ expected = DataFrame(
1412
+ {
1413
+ "A": [1, 2, 3],
1414
+ "B": [4.0, 5, 6],
1415
+ "F": [1.0, 1, float("nan")],
1416
+ "G": ["abc", "abc", float("nan")],
1417
+ }
1418
+ )
1419
+ tm.assert_frame_equal(df, expected)
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_take.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ import pandas._testing as tm
4
+
5
+
6
+ class TestDataFrameTake:
7
+ def test_take_slices_deprecated(self, float_frame):
8
+ # GH#51539
9
+ df = float_frame
10
+
11
+ slc = slice(0, 4, 1)
12
+ with tm.assert_produces_warning(FutureWarning):
13
+ df.take(slc, axis=0)
14
+ with tm.assert_produces_warning(FutureWarning):
15
+ df.take(slc, axis=1)
16
+
17
+ def test_take(self, float_frame):
18
+ # homogeneous
19
+ order = [3, 1, 2, 0]
20
+ for df in [float_frame]:
21
+ result = df.take(order, axis=0)
22
+ expected = df.reindex(df.index.take(order))
23
+ tm.assert_frame_equal(result, expected)
24
+
25
+ # axis = 1
26
+ result = df.take(order, axis=1)
27
+ expected = df.loc[:, ["D", "B", "C", "A"]]
28
+ tm.assert_frame_equal(result, expected, check_names=False)
29
+
30
+ # negative indices
31
+ order = [2, 1, -1]
32
+ for df in [float_frame]:
33
+ result = df.take(order, axis=0)
34
+ expected = df.reindex(df.index.take(order))
35
+ tm.assert_frame_equal(result, expected)
36
+
37
+ result = df.take(order, axis=0)
38
+ tm.assert_frame_equal(result, expected)
39
+
40
+ # axis = 1
41
+ result = df.take(order, axis=1)
42
+ expected = df.loc[:, ["C", "B", "D"]]
43
+ tm.assert_frame_equal(result, expected, check_names=False)
44
+
45
+ # illegal indices
46
+ msg = "indices are out-of-bounds"
47
+ with pytest.raises(IndexError, match=msg):
48
+ df.take([3, 1, 2, 30], axis=0)
49
+ with pytest.raises(IndexError, match=msg):
50
+ df.take([3, 1, 2, -31], axis=0)
51
+ with pytest.raises(IndexError, match=msg):
52
+ df.take([3, 1, 2, 5], axis=1)
53
+ with pytest.raises(IndexError, match=msg):
54
+ df.take([3, 1, 2, -5], axis=1)
55
+
56
+ def test_take_mixed_type(self, float_string_frame):
57
+ # mixed-dtype
58
+ order = [4, 1, 2, 0, 3]
59
+ for df in [float_string_frame]:
60
+ result = df.take(order, axis=0)
61
+ expected = df.reindex(df.index.take(order))
62
+ tm.assert_frame_equal(result, expected)
63
+
64
+ # axis = 1
65
+ result = df.take(order, axis=1)
66
+ expected = df.loc[:, ["foo", "B", "C", "A", "D"]]
67
+ tm.assert_frame_equal(result, expected)
68
+
69
+ # negative indices
70
+ order = [4, 1, -2]
71
+ for df in [float_string_frame]:
72
+ result = df.take(order, axis=0)
73
+ expected = df.reindex(df.index.take(order))
74
+ tm.assert_frame_equal(result, expected)
75
+
76
+ # axis = 1
77
+ result = df.take(order, axis=1)
78
+ expected = df.loc[:, ["foo", "B", "D"]]
79
+ tm.assert_frame_equal(result, expected)
80
+
81
+ def test_take_mixed_numeric(self, mixed_float_frame, mixed_int_frame):
82
+ # by dtype
83
+ order = [1, 2, 0, 3]
84
+ for df in [mixed_float_frame, mixed_int_frame]:
85
+ result = df.take(order, axis=0)
86
+ expected = df.reindex(df.index.take(order))
87
+ tm.assert_frame_equal(result, expected)
88
+
89
+ # axis = 1
90
+ result = df.take(order, axis=1)
91
+ expected = df.loc[:, ["B", "C", "A", "D"]]
92
+ tm.assert_frame_equal(result, expected)
lib/python3.12/site-packages/pandas/tests/frame/indexing/test_where.py ADDED
@@ -0,0 +1,1099 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+
3
+ from hypothesis import given
4
+ import numpy as np
5
+ import pytest
6
+
7
+ from pandas.core.dtypes.common import is_scalar
8
+
9
+ import pandas as pd
10
+ from pandas import (
11
+ DataFrame,
12
+ DatetimeIndex,
13
+ Index,
14
+ Series,
15
+ StringDtype,
16
+ Timestamp,
17
+ date_range,
18
+ isna,
19
+ )
20
+ import pandas._testing as tm
21
+ from pandas._testing._hypothesis import OPTIONAL_ONE_OF_ALL
22
+
23
+
24
+ @pytest.fixture(params=["default", "float_string", "mixed_float", "mixed_int"])
25
+ def where_frame(request, float_string_frame, mixed_float_frame, mixed_int_frame):
26
+ if request.param == "default":
27
+ return DataFrame(
28
+ np.random.default_rng(2).standard_normal((5, 3)), columns=["A", "B", "C"]
29
+ )
30
+ if request.param == "float_string":
31
+ return float_string_frame
32
+ if request.param == "mixed_float":
33
+ return mixed_float_frame
34
+ if request.param == "mixed_int":
35
+ return mixed_int_frame
36
+
37
+
38
+ def _safe_add(df):
39
+ # only add to the numeric items
40
+ def is_ok(s):
41
+ return (
42
+ issubclass(s.dtype.type, (np.integer, np.floating)) and s.dtype != "uint8"
43
+ )
44
+
45
+ return DataFrame(dict((c, s + 1) if is_ok(s) else (c, s) for c, s in df.items()))
46
+
47
+
48
+ class TestDataFrameIndexingWhere:
49
+ def test_where_get(self, where_frame, float_string_frame):
50
+ def _check_get(df, cond, check_dtypes=True):
51
+ other1 = _safe_add(df)
52
+ rs = df.where(cond, other1)
53
+ rs2 = df.where(cond.values, other1)
54
+ for k, v in rs.items():
55
+ exp = Series(np.where(cond[k], df[k], other1[k]), index=v.index)
56
+ tm.assert_series_equal(v, exp, check_names=False)
57
+ tm.assert_frame_equal(rs, rs2)
58
+
59
+ # dtypes
60
+ if check_dtypes:
61
+ assert (rs.dtypes == df.dtypes).all()
62
+
63
+ # check getting
64
+ df = where_frame
65
+ if df is float_string_frame:
66
+ msg = "'>' not supported between instances of 'str' and 'int'"
67
+ with pytest.raises(TypeError, match=msg):
68
+ df > 0
69
+ return
70
+ cond = df > 0
71
+ _check_get(df, cond)
72
+
73
+ def test_where_upcasting(self):
74
+ # upcasting case (GH # 2794)
75
+ df = DataFrame(
76
+ {
77
+ c: Series([1] * 3, dtype=c)
78
+ for c in ["float32", "float64", "int32", "int64"]
79
+ }
80
+ )
81
+ df.iloc[1, :] = 0
82
+ result = df.dtypes
83
+ expected = Series(
84
+ [
85
+ np.dtype("float32"),
86
+ np.dtype("float64"),
87
+ np.dtype("int32"),
88
+ np.dtype("int64"),
89
+ ],
90
+ index=["float32", "float64", "int32", "int64"],
91
+ )
92
+
93
+ # when we don't preserve boolean casts
94
+ #
95
+ # expected = Series({ 'float32' : 1, 'float64' : 3 })
96
+
97
+ tm.assert_series_equal(result, expected)
98
+
99
+ @pytest.mark.filterwarnings("ignore:Downcasting object dtype arrays:FutureWarning")
100
+ def test_where_alignment(self, where_frame, float_string_frame):
101
+ # aligning
102
+ def _check_align(df, cond, other, check_dtypes=True):
103
+ rs = df.where(cond, other)
104
+ for i, k in enumerate(rs.columns):
105
+ result = rs[k]
106
+ d = df[k].values
107
+ c = cond[k].reindex(df[k].index).fillna(False).values
108
+
109
+ if is_scalar(other):
110
+ o = other
111
+ elif isinstance(other, np.ndarray):
112
+ o = Series(other[:, i], index=result.index).values
113
+ else:
114
+ o = other[k].values
115
+
116
+ new_values = d if c.all() else np.where(c, d, o)
117
+ expected = Series(new_values, index=result.index, name=k)
118
+
119
+ # since we can't always have the correct numpy dtype
120
+ # as numpy doesn't know how to downcast, don't check
121
+ tm.assert_series_equal(result, expected, check_dtype=False)
122
+
123
+ # dtypes
124
+ # can't check dtype when other is an ndarray
125
+
126
+ if check_dtypes and not isinstance(other, np.ndarray):
127
+ assert (rs.dtypes == df.dtypes).all()
128
+
129
+ df = where_frame
130
+ if df is float_string_frame:
131
+ msg = "'>' not supported between instances of 'str' and 'int'"
132
+ with pytest.raises(TypeError, match=msg):
133
+ df > 0
134
+ return
135
+
136
+ # other is a frame
137
+ cond = (df > 0)[1:]
138
+ _check_align(df, cond, _safe_add(df))
139
+
140
+ # check other is ndarray
141
+ cond = df > 0
142
+ _check_align(df, cond, (_safe_add(df).values))
143
+
144
+ # integers are upcast, so don't check the dtypes
145
+ cond = df > 0
146
+ check_dtypes = all(not issubclass(s.type, np.integer) for s in df.dtypes)
147
+ _check_align(df, cond, np.nan, check_dtypes=check_dtypes)
148
+
149
+ # Ignore deprecation warning in Python 3.12 for inverting a bool
150
+ @pytest.mark.filterwarnings("ignore::DeprecationWarning")
151
+ def test_where_invalid(self):
152
+ # invalid conditions
153
+ df = DataFrame(
154
+ np.random.default_rng(2).standard_normal((5, 3)), columns=["A", "B", "C"]
155
+ )
156
+ cond = df > 0
157
+
158
+ err1 = (df + 1).values[0:2, :]
159
+ msg = "other must be the same shape as self when an ndarray"
160
+ with pytest.raises(ValueError, match=msg):
161
+ df.where(cond, err1)
162
+
163
+ err2 = cond.iloc[:2, :].values
164
+ other1 = _safe_add(df)
165
+ msg = "Array conditional must be same shape as self"
166
+ with pytest.raises(ValueError, match=msg):
167
+ df.where(err2, other1)
168
+
169
+ with pytest.raises(ValueError, match=msg):
170
+ df.mask(True)
171
+ with pytest.raises(ValueError, match=msg):
172
+ df.mask(0)
173
+
174
+ @pytest.mark.filterwarnings("ignore:Downcasting object dtype arrays:FutureWarning")
175
+ def test_where_set(self, where_frame, float_string_frame, mixed_int_frame):
176
+ # where inplace
177
+
178
+ def _check_set(df, cond, check_dtypes=True):
179
+ dfi = df.copy()
180
+ econd = cond.reindex_like(df).fillna(True).infer_objects(copy=False)
181
+ expected = dfi.mask(~econd)
182
+
183
+ return_value = dfi.where(cond, np.nan, inplace=True)
184
+ assert return_value is None
185
+ tm.assert_frame_equal(dfi, expected)
186
+
187
+ # dtypes (and confirm upcasts)x
188
+ if check_dtypes:
189
+ for k, v in df.dtypes.items():
190
+ if issubclass(v.type, np.integer) and not cond[k].all():
191
+ v = np.dtype("float64")
192
+ assert dfi[k].dtype == v
193
+
194
+ df = where_frame
195
+ if df is float_string_frame:
196
+ msg = "'>' not supported between instances of 'str' and 'int'"
197
+ with pytest.raises(TypeError, match=msg):
198
+ df > 0
199
+ return
200
+ if df is mixed_int_frame:
201
+ df = df.astype("float64")
202
+
203
+ cond = df > 0
204
+ _check_set(df, cond)
205
+
206
+ cond = df >= 0
207
+ _check_set(df, cond)
208
+
209
+ # aligning
210
+ cond = (df >= 0)[1:]
211
+ _check_set(df, cond)
212
+
213
+ def test_where_series_slicing(self):
214
+ # GH 10218
215
+ # test DataFrame.where with Series slicing
216
+ df = DataFrame({"a": range(3), "b": range(4, 7)})
217
+ result = df.where(df["a"] == 1)
218
+ expected = df[df["a"] == 1].reindex(df.index)
219
+ tm.assert_frame_equal(result, expected)
220
+
221
+ @pytest.mark.parametrize("klass", [list, tuple, np.array])
222
+ def test_where_array_like(self, klass):
223
+ # see gh-15414
224
+ df = DataFrame({"a": [1, 2, 3]})
225
+ cond = [[False], [True], [True]]
226
+ expected = DataFrame({"a": [np.nan, 2, 3]})
227
+
228
+ result = df.where(klass(cond))
229
+ tm.assert_frame_equal(result, expected)
230
+
231
+ df["b"] = 2
232
+ expected["b"] = [2, np.nan, 2]
233
+ cond = [[False, True], [True, False], [True, True]]
234
+
235
+ result = df.where(klass(cond))
236
+ tm.assert_frame_equal(result, expected)
237
+
238
+ @pytest.mark.parametrize(
239
+ "cond",
240
+ [
241
+ [[1], [0], [1]],
242
+ Series([[2], [5], [7]]),
243
+ DataFrame({"a": [2, 5, 7]}),
244
+ [["True"], ["False"], ["True"]],
245
+ [[Timestamp("2017-01-01")], [pd.NaT], [Timestamp("2017-01-02")]],
246
+ ],
247
+ )
248
+ def test_where_invalid_input_single(self, cond):
249
+ # see gh-15414: only boolean arrays accepted
250
+ df = DataFrame({"a": [1, 2, 3]})
251
+ msg = "Boolean array expected for the condition"
252
+
253
+ with pytest.raises(ValueError, match=msg):
254
+ df.where(cond)
255
+
256
+ @pytest.mark.parametrize(
257
+ "cond",
258
+ [
259
+ [[0, 1], [1, 0], [1, 1]],
260
+ Series([[0, 2], [5, 0], [4, 7]]),
261
+ [["False", "True"], ["True", "False"], ["True", "True"]],
262
+ DataFrame({"a": [2, 5, 7], "b": [4, 8, 9]}),
263
+ [
264
+ [pd.NaT, Timestamp("2017-01-01")],
265
+ [Timestamp("2017-01-02"), pd.NaT],
266
+ [Timestamp("2017-01-03"), Timestamp("2017-01-03")],
267
+ ],
268
+ ],
269
+ )
270
+ def test_where_invalid_input_multiple(self, cond):
271
+ # see gh-15414: only boolean arrays accepted
272
+ df = DataFrame({"a": [1, 2, 3], "b": [2, 2, 2]})
273
+ msg = "Boolean array expected for the condition"
274
+
275
+ with pytest.raises(ValueError, match=msg):
276
+ df.where(cond)
277
+
278
+ def test_where_dataframe_col_match(self):
279
+ df = DataFrame([[1, 2, 3], [4, 5, 6]])
280
+ cond = DataFrame([[True, False, True], [False, False, True]])
281
+
282
+ result = df.where(cond)
283
+ expected = DataFrame([[1.0, np.nan, 3], [np.nan, np.nan, 6]])
284
+ tm.assert_frame_equal(result, expected)
285
+
286
+ # this *does* align, though has no matching columns
287
+ cond.columns = ["a", "b", "c"]
288
+ result = df.where(cond)
289
+ expected = DataFrame(np.nan, index=df.index, columns=df.columns)
290
+ tm.assert_frame_equal(result, expected)
291
+
292
+ def test_where_ndframe_align(self):
293
+ msg = "Array conditional must be same shape as self"
294
+ df = DataFrame([[1, 2, 3], [4, 5, 6]])
295
+
296
+ cond = [True]
297
+ with pytest.raises(ValueError, match=msg):
298
+ df.where(cond)
299
+
300
+ expected = DataFrame([[1, 2, 3], [np.nan, np.nan, np.nan]])
301
+
302
+ out = df.where(Series(cond))
303
+ tm.assert_frame_equal(out, expected)
304
+
305
+ cond = np.array([False, True, False, True])
306
+ with pytest.raises(ValueError, match=msg):
307
+ df.where(cond)
308
+
309
+ expected = DataFrame([[np.nan, np.nan, np.nan], [4, 5, 6]])
310
+
311
+ out = df.where(Series(cond))
312
+ tm.assert_frame_equal(out, expected)
313
+
314
+ def test_where_bug(self):
315
+ # see gh-2793
316
+ df = DataFrame(
317
+ {"a": [1.0, 2.0, 3.0, 4.0], "b": [4.0, 3.0, 2.0, 1.0]}, dtype="float64"
318
+ )
319
+ expected = DataFrame(
320
+ {"a": [np.nan, np.nan, 3.0, 4.0], "b": [4.0, 3.0, np.nan, np.nan]},
321
+ dtype="float64",
322
+ )
323
+ result = df.where(df > 2, np.nan)
324
+ tm.assert_frame_equal(result, expected)
325
+
326
+ result = df.copy()
327
+ return_value = result.where(result > 2, np.nan, inplace=True)
328
+ assert return_value is None
329
+ tm.assert_frame_equal(result, expected)
330
+
331
+ def test_where_bug_mixed(self, any_signed_int_numpy_dtype):
332
+ # see gh-2793
333
+ df = DataFrame(
334
+ {
335
+ "a": np.array([1, 2, 3, 4], dtype=any_signed_int_numpy_dtype),
336
+ "b": np.array([4.0, 3.0, 2.0, 1.0], dtype="float64"),
337
+ }
338
+ )
339
+
340
+ expected = DataFrame(
341
+ {"a": [-1, -1, 3, 4], "b": [4.0, 3.0, -1, -1]},
342
+ ).astype({"a": any_signed_int_numpy_dtype, "b": "float64"})
343
+
344
+ result = df.where(df > 2, -1)
345
+ tm.assert_frame_equal(result, expected)
346
+
347
+ result = df.copy()
348
+ return_value = result.where(result > 2, -1, inplace=True)
349
+ assert return_value is None
350
+ tm.assert_frame_equal(result, expected)
351
+
352
+ def test_where_bug_transposition(self):
353
+ # see gh-7506
354
+ a = DataFrame({0: [1, 2], 1: [3, 4], 2: [5, 6]})
355
+ b = DataFrame({0: [np.nan, 8], 1: [9, np.nan], 2: [np.nan, np.nan]})
356
+ do_not_replace = b.isna() | (a > b)
357
+
358
+ expected = a.copy()
359
+ expected[~do_not_replace] = b
360
+
361
+ msg = "Downcasting behavior in Series and DataFrame methods 'where'"
362
+ with tm.assert_produces_warning(FutureWarning, match=msg):
363
+ result = a.where(do_not_replace, b)
364
+ tm.assert_frame_equal(result, expected)
365
+
366
+ a = DataFrame({0: [4, 6], 1: [1, 0]})
367
+ b = DataFrame({0: [np.nan, 3], 1: [3, np.nan]})
368
+ do_not_replace = b.isna() | (a > b)
369
+
370
+ expected = a.copy()
371
+ expected[~do_not_replace] = b
372
+
373
+ with tm.assert_produces_warning(FutureWarning, match=msg):
374
+ result = a.where(do_not_replace, b)
375
+ tm.assert_frame_equal(result, expected)
376
+
377
+ def test_where_datetime(self):
378
+ # GH 3311
379
+ df = DataFrame(
380
+ {
381
+ "A": date_range("20130102", periods=5),
382
+ "B": date_range("20130104", periods=5),
383
+ "C": np.random.default_rng(2).standard_normal(5),
384
+ }
385
+ )
386
+
387
+ stamp = datetime(2013, 1, 3)
388
+ msg = "'>' not supported between instances of 'float' and 'datetime.datetime'"
389
+ with pytest.raises(TypeError, match=msg):
390
+ df > stamp
391
+
392
+ result = df[df.iloc[:, :-1] > stamp]
393
+
394
+ expected = df.copy()
395
+ expected.loc[[0, 1], "A"] = np.nan
396
+
397
+ expected.loc[:, "C"] = np.nan
398
+ tm.assert_frame_equal(result, expected)
399
+
400
+ def test_where_none(self):
401
+ # GH 4667
402
+ # setting with None changes dtype
403
+ df = DataFrame({"series": Series(range(10))}).astype(float)
404
+ df[df > 7] = None
405
+ expected = DataFrame(
406
+ {"series": Series([0, 1, 2, 3, 4, 5, 6, 7, np.nan, np.nan])}
407
+ )
408
+ tm.assert_frame_equal(df, expected)
409
+
410
+ # GH 7656
411
+ df = DataFrame(
412
+ [
413
+ {"A": 1, "B": np.nan, "C": "Test"},
414
+ {"A": np.nan, "B": "Test", "C": np.nan},
415
+ ]
416
+ )
417
+
418
+ orig = df.copy()
419
+
420
+ mask = ~isna(df)
421
+ df.where(mask, None, inplace=True)
422
+ expected = DataFrame(
423
+ {
424
+ "A": [1.0, np.nan],
425
+ "B": [None, "Test"],
426
+ "C": ["Test", None],
427
+ }
428
+ )
429
+ tm.assert_frame_equal(df, expected)
430
+
431
+ df = orig.copy()
432
+ df[~mask] = None
433
+ tm.assert_frame_equal(df, expected)
434
+
435
+ def test_where_empty_df_and_empty_cond_having_non_bool_dtypes(self):
436
+ # see gh-21947
437
+ df = DataFrame(columns=["a"])
438
+ cond = df
439
+ assert (cond.dtypes == object).all()
440
+
441
+ result = df.where(cond)
442
+ tm.assert_frame_equal(result, df)
443
+
444
+ def test_where_align(self):
445
+ def create():
446
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 3)))
447
+ df.iloc[3:5, 0] = np.nan
448
+ df.iloc[4:6, 1] = np.nan
449
+ df.iloc[5:8, 2] = np.nan
450
+ return df
451
+
452
+ # series
453
+ df = create()
454
+ expected = df.fillna(df.mean())
455
+ result = df.where(pd.notna(df), df.mean(), axis="columns")
456
+ tm.assert_frame_equal(result, expected)
457
+
458
+ return_value = df.where(pd.notna(df), df.mean(), inplace=True, axis="columns")
459
+ assert return_value is None
460
+ tm.assert_frame_equal(df, expected)
461
+
462
+ df = create().fillna(0)
463
+ expected = df.apply(lambda x, y: x.where(x > 0, y), y=df[0])
464
+ result = df.where(df > 0, df[0], axis="index")
465
+ tm.assert_frame_equal(result, expected)
466
+ result = df.where(df > 0, df[0], axis="rows")
467
+ tm.assert_frame_equal(result, expected)
468
+
469
+ # frame
470
+ df = create()
471
+ expected = df.fillna(1)
472
+ result = df.where(
473
+ pd.notna(df), DataFrame(1, index=df.index, columns=df.columns)
474
+ )
475
+ tm.assert_frame_equal(result, expected)
476
+
477
+ def test_where_complex(self):
478
+ # GH 6345
479
+ expected = DataFrame([[1 + 1j, 2], [np.nan, 4 + 1j]], columns=["a", "b"])
480
+ df = DataFrame([[1 + 1j, 2], [5 + 1j, 4 + 1j]], columns=["a", "b"])
481
+ df[df.abs() >= 5] = np.nan
482
+ tm.assert_frame_equal(df, expected)
483
+
484
+ def test_where_axis(self):
485
+ # GH 9736
486
+ df = DataFrame(np.random.default_rng(2).standard_normal((2, 2)))
487
+ mask = DataFrame([[False, False], [False, False]])
488
+ ser = Series([0, 1])
489
+
490
+ expected = DataFrame([[0, 0], [1, 1]], dtype="float64")
491
+ result = df.where(mask, ser, axis="index")
492
+ tm.assert_frame_equal(result, expected)
493
+
494
+ result = df.copy()
495
+ return_value = result.where(mask, ser, axis="index", inplace=True)
496
+ assert return_value is None
497
+ tm.assert_frame_equal(result, expected)
498
+
499
+ expected = DataFrame([[0, 1], [0, 1]], dtype="float64")
500
+ result = df.where(mask, ser, axis="columns")
501
+ tm.assert_frame_equal(result, expected)
502
+
503
+ result = df.copy()
504
+ return_value = result.where(mask, ser, axis="columns", inplace=True)
505
+ assert return_value is None
506
+ tm.assert_frame_equal(result, expected)
507
+
508
+ def test_where_axis_with_upcast(self):
509
+ # Upcast needed
510
+ df = DataFrame([[1, 2], [3, 4]], dtype="int64")
511
+ mask = DataFrame([[False, False], [False, False]])
512
+ ser = Series([0, np.nan])
513
+
514
+ expected = DataFrame([[0, 0], [np.nan, np.nan]], dtype="float64")
515
+ result = df.where(mask, ser, axis="index")
516
+ tm.assert_frame_equal(result, expected)
517
+
518
+ result = df.copy()
519
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
520
+ return_value = result.where(mask, ser, axis="index", inplace=True)
521
+ assert return_value is None
522
+ tm.assert_frame_equal(result, expected)
523
+
524
+ expected = DataFrame([[0, np.nan], [0, np.nan]])
525
+ result = df.where(mask, ser, axis="columns")
526
+ tm.assert_frame_equal(result, expected)
527
+
528
+ expected = DataFrame(
529
+ {
530
+ 0: np.array([0, 0], dtype="int64"),
531
+ 1: np.array([np.nan, np.nan], dtype="float64"),
532
+ }
533
+ )
534
+ result = df.copy()
535
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
536
+ return_value = result.where(mask, ser, axis="columns", inplace=True)
537
+ assert return_value is None
538
+ tm.assert_frame_equal(result, expected)
539
+
540
+ def test_where_axis_multiple_dtypes(self):
541
+ # Multiple dtypes (=> multiple Blocks)
542
+ df = pd.concat(
543
+ [
544
+ DataFrame(np.random.default_rng(2).standard_normal((10, 2))),
545
+ DataFrame(
546
+ np.random.default_rng(2).integers(0, 10, size=(10, 2)),
547
+ dtype="int64",
548
+ ),
549
+ ],
550
+ ignore_index=True,
551
+ axis=1,
552
+ )
553
+ mask = DataFrame(False, columns=df.columns, index=df.index)
554
+ s1 = Series(1, index=df.columns)
555
+ s2 = Series(2, index=df.index)
556
+
557
+ result = df.where(mask, s1, axis="columns")
558
+ expected = DataFrame(1.0, columns=df.columns, index=df.index)
559
+ expected[2] = expected[2].astype("int64")
560
+ expected[3] = expected[3].astype("int64")
561
+ tm.assert_frame_equal(result, expected)
562
+
563
+ result = df.copy()
564
+ return_value = result.where(mask, s1, axis="columns", inplace=True)
565
+ assert return_value is None
566
+ tm.assert_frame_equal(result, expected)
567
+
568
+ result = df.where(mask, s2, axis="index")
569
+ expected = DataFrame(2.0, columns=df.columns, index=df.index)
570
+ expected[2] = expected[2].astype("int64")
571
+ expected[3] = expected[3].astype("int64")
572
+ tm.assert_frame_equal(result, expected)
573
+
574
+ result = df.copy()
575
+ return_value = result.where(mask, s2, axis="index", inplace=True)
576
+ assert return_value is None
577
+ tm.assert_frame_equal(result, expected)
578
+
579
+ # DataFrame vs DataFrame
580
+ d1 = df.copy().drop(1, axis=0)
581
+ # Explicit cast to avoid implicit cast when setting value to np.nan
582
+ expected = df.copy().astype("float")
583
+ expected.loc[1, :] = np.nan
584
+
585
+ result = df.where(mask, d1)
586
+ tm.assert_frame_equal(result, expected)
587
+ result = df.where(mask, d1, axis="index")
588
+ tm.assert_frame_equal(result, expected)
589
+ result = df.copy()
590
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
591
+ return_value = result.where(mask, d1, inplace=True)
592
+ assert return_value is None
593
+ tm.assert_frame_equal(result, expected)
594
+ result = df.copy()
595
+ with tm.assert_produces_warning(FutureWarning, match="incompatible dtype"):
596
+ return_value = result.where(mask, d1, inplace=True, axis="index")
597
+ assert return_value is None
598
+ tm.assert_frame_equal(result, expected)
599
+
600
+ d2 = df.copy().drop(1, axis=1)
601
+ expected = df.copy()
602
+ expected.loc[:, 1] = np.nan
603
+
604
+ result = df.where(mask, d2)
605
+ tm.assert_frame_equal(result, expected)
606
+ result = df.where(mask, d2, axis="columns")
607
+ tm.assert_frame_equal(result, expected)
608
+ result = df.copy()
609
+ return_value = result.where(mask, d2, inplace=True)
610
+ assert return_value is None
611
+ tm.assert_frame_equal(result, expected)
612
+ result = df.copy()
613
+ return_value = result.where(mask, d2, inplace=True, axis="columns")
614
+ assert return_value is None
615
+ tm.assert_frame_equal(result, expected)
616
+
617
+ def test_where_callable(self):
618
+ # GH 12533
619
+ df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
620
+ result = df.where(lambda x: x > 4, lambda x: x + 1)
621
+ exp = DataFrame([[2, 3, 4], [5, 5, 6], [7, 8, 9]])
622
+ tm.assert_frame_equal(result, exp)
623
+ tm.assert_frame_equal(result, df.where(df > 4, df + 1))
624
+
625
+ # return ndarray and scalar
626
+ result = df.where(lambda x: (x % 2 == 0).values, lambda x: 99)
627
+ exp = DataFrame([[99, 2, 99], [4, 99, 6], [99, 8, 99]])
628
+ tm.assert_frame_equal(result, exp)
629
+ tm.assert_frame_equal(result, df.where(df % 2 == 0, 99))
630
+
631
+ # chain
632
+ result = (df + 2).where(lambda x: x > 8, lambda x: x + 10)
633
+ exp = DataFrame([[13, 14, 15], [16, 17, 18], [9, 10, 11]])
634
+ tm.assert_frame_equal(result, exp)
635
+ tm.assert_frame_equal(result, (df + 2).where((df + 2) > 8, (df + 2) + 10))
636
+
637
+ def test_where_tz_values(self, tz_naive_fixture, frame_or_series):
638
+ obj1 = DataFrame(
639
+ DatetimeIndex(["20150101", "20150102", "20150103"], tz=tz_naive_fixture),
640
+ columns=["date"],
641
+ )
642
+ obj2 = DataFrame(
643
+ DatetimeIndex(["20150103", "20150104", "20150105"], tz=tz_naive_fixture),
644
+ columns=["date"],
645
+ )
646
+ mask = DataFrame([True, True, False], columns=["date"])
647
+ exp = DataFrame(
648
+ DatetimeIndex(["20150101", "20150102", "20150105"], tz=tz_naive_fixture),
649
+ columns=["date"],
650
+ )
651
+ if frame_or_series is Series:
652
+ obj1 = obj1["date"]
653
+ obj2 = obj2["date"]
654
+ mask = mask["date"]
655
+ exp = exp["date"]
656
+
657
+ result = obj1.where(mask, obj2)
658
+ tm.assert_equal(exp, result)
659
+
660
+ def test_df_where_change_dtype(self):
661
+ # GH#16979
662
+ df = DataFrame(np.arange(2 * 3).reshape(2, 3), columns=list("ABC"))
663
+ mask = np.array([[True, False, False], [False, False, True]])
664
+
665
+ result = df.where(mask)
666
+ expected = DataFrame(
667
+ [[0, np.nan, np.nan], [np.nan, np.nan, 5]], columns=list("ABC")
668
+ )
669
+
670
+ tm.assert_frame_equal(result, expected)
671
+
672
+ @pytest.mark.parametrize("kwargs", [{}, {"other": None}])
673
+ def test_df_where_with_category(self, kwargs):
674
+ # GH#16979
675
+ data = np.arange(2 * 3, dtype=np.int64).reshape(2, 3)
676
+ df = DataFrame(data, columns=list("ABC"))
677
+ mask = np.array([[True, False, False], [False, False, True]])
678
+
679
+ # change type to category
680
+ df.A = df.A.astype("category")
681
+ df.B = df.B.astype("category")
682
+ df.C = df.C.astype("category")
683
+
684
+ result = df.where(mask, **kwargs)
685
+ A = pd.Categorical([0, np.nan], categories=[0, 3])
686
+ B = pd.Categorical([np.nan, np.nan], categories=[1, 4])
687
+ C = pd.Categorical([np.nan, 5], categories=[2, 5])
688
+ expected = DataFrame({"A": A, "B": B, "C": C})
689
+
690
+ tm.assert_frame_equal(result, expected)
691
+
692
+ # Check Series.where while we're here
693
+ result = df.A.where(mask[:, 0], **kwargs)
694
+ expected = Series(A, name="A")
695
+
696
+ tm.assert_series_equal(result, expected)
697
+
698
+ def test_where_categorical_filtering(self):
699
+ # GH#22609 Verify filtering operations on DataFrames with categorical Series
700
+ df = DataFrame(data=[[0, 0], [1, 1]], columns=["a", "b"])
701
+ df["b"] = df["b"].astype("category")
702
+
703
+ result = df.where(df["a"] > 0)
704
+ # Explicitly cast to 'float' to avoid implicit cast when setting np.nan
705
+ expected = df.copy().astype({"a": "float"})
706
+ expected.loc[0, :] = np.nan
707
+
708
+ tm.assert_equal(result, expected)
709
+
710
+ def test_where_ea_other(self):
711
+ # GH#38729/GH#38742
712
+ df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
713
+ arr = pd.array([7, pd.NA, 9])
714
+ ser = Series(arr)
715
+ mask = np.ones(df.shape, dtype=bool)
716
+ mask[1, :] = False
717
+
718
+ # TODO: ideally we would get Int64 instead of object
719
+ result = df.where(mask, ser, axis=0)
720
+ expected = DataFrame({"A": [1, np.nan, 3], "B": [4, np.nan, 6]})
721
+ tm.assert_frame_equal(result, expected)
722
+
723
+ ser2 = Series(arr[:2], index=["A", "B"])
724
+ expected = DataFrame({"A": [1, 7, 3], "B": [4, np.nan, 6]})
725
+ result = df.where(mask, ser2, axis=1)
726
+ tm.assert_frame_equal(result, expected)
727
+
728
+ def test_where_interval_noop(self):
729
+ # GH#44181
730
+ df = DataFrame([pd.Interval(0, 0)])
731
+ res = df.where(df.notna())
732
+ tm.assert_frame_equal(res, df)
733
+
734
+ ser = df[0]
735
+ res = ser.where(ser.notna())
736
+ tm.assert_series_equal(res, ser)
737
+
738
+ def test_where_interval_fullop_downcast(self, frame_or_series):
739
+ # GH#45768
740
+ obj = frame_or_series([pd.Interval(0, 0)] * 2)
741
+ other = frame_or_series([1.0, 2.0])
742
+
743
+ msg = "Downcasting behavior in Series and DataFrame methods 'where'"
744
+ with tm.assert_produces_warning(FutureWarning, match=msg):
745
+ res = obj.where(~obj.notna(), other)
746
+
747
+ # since all entries are being changed, we will downcast result
748
+ # from object to ints (not floats)
749
+ tm.assert_equal(res, other.astype(np.int64))
750
+
751
+ # unlike where, Block.putmask does not downcast
752
+ with tm.assert_produces_warning(
753
+ FutureWarning, match="Setting an item of incompatible dtype"
754
+ ):
755
+ obj.mask(obj.notna(), other, inplace=True)
756
+ tm.assert_equal(obj, other.astype(object))
757
+
758
+ @pytest.mark.parametrize(
759
+ "dtype",
760
+ [
761
+ "timedelta64[ns]",
762
+ "datetime64[ns]",
763
+ "datetime64[ns, Asia/Tokyo]",
764
+ "Period[D]",
765
+ ],
766
+ )
767
+ def test_where_datetimelike_noop(self, dtype):
768
+ # GH#45135, analogue to GH#44181 for Period don't raise on no-op
769
+ # For td64/dt64/dt64tz we already don't raise, but also are
770
+ # checking that we don't unnecessarily upcast to object.
771
+ with tm.assert_produces_warning(FutureWarning, match="is deprecated"):
772
+ ser = Series(np.arange(3) * 10**9, dtype=np.int64).view(dtype)
773
+ df = ser.to_frame()
774
+ mask = np.array([False, False, False])
775
+
776
+ res = ser.where(~mask, "foo")
777
+ tm.assert_series_equal(res, ser)
778
+
779
+ mask2 = mask.reshape(-1, 1)
780
+ res2 = df.where(~mask2, "foo")
781
+ tm.assert_frame_equal(res2, df)
782
+
783
+ res3 = ser.mask(mask, "foo")
784
+ tm.assert_series_equal(res3, ser)
785
+
786
+ res4 = df.mask(mask2, "foo")
787
+ tm.assert_frame_equal(res4, df)
788
+
789
+ # opposite case where we are replacing *all* values -> we downcast
790
+ # from object dtype # GH#45768
791
+ msg = "Downcasting behavior in Series and DataFrame methods 'where'"
792
+ with tm.assert_produces_warning(FutureWarning, match=msg):
793
+ res5 = df.where(mask2, 4)
794
+ expected = DataFrame(4, index=df.index, columns=df.columns)
795
+ tm.assert_frame_equal(res5, expected)
796
+
797
+ # unlike where, Block.putmask does not downcast
798
+ with tm.assert_produces_warning(
799
+ FutureWarning, match="Setting an item of incompatible dtype"
800
+ ):
801
+ df.mask(~mask2, 4, inplace=True)
802
+ tm.assert_frame_equal(df, expected.astype(object))
803
+
804
+
805
+ def test_where_int_downcasting_deprecated():
806
+ # GH#44597
807
+ arr = np.arange(6).astype(np.int16).reshape(3, 2)
808
+ df = DataFrame(arr)
809
+
810
+ mask = np.zeros(arr.shape, dtype=bool)
811
+ mask[:, 0] = True
812
+
813
+ res = df.where(mask, 2**17)
814
+
815
+ expected = DataFrame({0: arr[:, 0], 1: np.array([2**17] * 3, dtype=np.int32)})
816
+ tm.assert_frame_equal(res, expected)
817
+
818
+
819
+ def test_where_copies_with_noop(frame_or_series):
820
+ # GH-39595
821
+ result = frame_or_series([1, 2, 3, 4])
822
+ expected = result.copy()
823
+ col = result[0] if frame_or_series is DataFrame else result
824
+
825
+ where_res = result.where(col < 5)
826
+ where_res *= 2
827
+
828
+ tm.assert_equal(result, expected)
829
+
830
+ where_res = result.where(col > 5, [1, 2, 3, 4])
831
+ where_res *= 2
832
+
833
+ tm.assert_equal(result, expected)
834
+
835
+
836
+ def test_where_string_dtype(frame_or_series):
837
+ # GH40824
838
+ obj = frame_or_series(
839
+ ["a", "b", "c", "d"], index=["id1", "id2", "id3", "id4"], dtype=StringDtype()
840
+ )
841
+ filtered_obj = frame_or_series(
842
+ ["b", "c"], index=["id2", "id3"], dtype=StringDtype()
843
+ )
844
+ filter_ser = Series([False, True, True, False])
845
+
846
+ result = obj.where(filter_ser, filtered_obj)
847
+ expected = frame_or_series(
848
+ [pd.NA, "b", "c", pd.NA],
849
+ index=["id1", "id2", "id3", "id4"],
850
+ dtype=StringDtype(),
851
+ )
852
+ tm.assert_equal(result, expected)
853
+
854
+ result = obj.mask(~filter_ser, filtered_obj)
855
+ tm.assert_equal(result, expected)
856
+
857
+ obj.mask(~filter_ser, filtered_obj, inplace=True)
858
+ tm.assert_equal(result, expected)
859
+
860
+
861
+ def test_where_bool_comparison():
862
+ # GH 10336
863
+ df_mask = DataFrame(
864
+ {"AAA": [True] * 4, "BBB": [False] * 4, "CCC": [True, False, True, False]}
865
+ )
866
+ result = df_mask.where(df_mask == False) # noqa: E712
867
+ expected = DataFrame(
868
+ {
869
+ "AAA": np.array([np.nan] * 4, dtype=object),
870
+ "BBB": [False] * 4,
871
+ "CCC": [np.nan, False, np.nan, False],
872
+ }
873
+ )
874
+ tm.assert_frame_equal(result, expected)
875
+
876
+
877
+ def test_where_none_nan_coerce():
878
+ # GH 15613
879
+ expected = DataFrame(
880
+ {
881
+ "A": [Timestamp("20130101"), pd.NaT, Timestamp("20130103")],
882
+ "B": [1, 2, np.nan],
883
+ }
884
+ )
885
+ result = expected.where(expected.notnull(), None)
886
+ tm.assert_frame_equal(result, expected)
887
+
888
+
889
+ def test_where_duplicate_axes_mixed_dtypes():
890
+ # GH 25399, verify manually masking is not affected anymore by dtype of column for
891
+ # duplicate axes.
892
+ result = DataFrame(data=[[0, np.nan]], columns=Index(["A", "A"]))
893
+ index, columns = result.axes
894
+ mask = DataFrame(data=[[True, True]], columns=columns, index=index)
895
+ a = result.astype(object).where(mask)
896
+ b = result.astype("f8").where(mask)
897
+ c = result.T.where(mask.T).T
898
+ d = result.where(mask) # used to fail with "cannot reindex from a duplicate axis"
899
+ tm.assert_frame_equal(a.astype("f8"), b.astype("f8"))
900
+ tm.assert_frame_equal(b.astype("f8"), c.astype("f8"))
901
+ tm.assert_frame_equal(c.astype("f8"), d.astype("f8"))
902
+
903
+
904
+ def test_where_columns_casting():
905
+ # GH 42295
906
+
907
+ df = DataFrame({"a": [1.0, 2.0], "b": [3, np.nan]})
908
+ expected = df.copy()
909
+ result = df.where(pd.notnull(df), None)
910
+ # make sure dtypes don't change
911
+ tm.assert_frame_equal(expected, result)
912
+
913
+
914
+ @pytest.mark.parametrize("as_cat", [True, False])
915
+ def test_where_period_invalid_na(frame_or_series, as_cat, request):
916
+ # GH#44697
917
+ idx = pd.period_range("2016-01-01", periods=3, freq="D")
918
+ if as_cat:
919
+ idx = idx.astype("category")
920
+ obj = frame_or_series(idx)
921
+
922
+ # NA value that we should *not* cast to Period dtype
923
+ tdnat = pd.NaT.to_numpy("m8[ns]")
924
+
925
+ mask = np.array([True, True, False], ndmin=obj.ndim).T
926
+
927
+ if as_cat:
928
+ msg = (
929
+ r"Cannot setitem on a Categorical with a new category \(NaT\), "
930
+ "set the categories first"
931
+ )
932
+ else:
933
+ msg = "value should be a 'Period'"
934
+
935
+ if as_cat:
936
+ with pytest.raises(TypeError, match=msg):
937
+ obj.where(mask, tdnat)
938
+
939
+ with pytest.raises(TypeError, match=msg):
940
+ obj.mask(mask, tdnat)
941
+
942
+ with pytest.raises(TypeError, match=msg):
943
+ obj.mask(mask, tdnat, inplace=True)
944
+
945
+ else:
946
+ # With PeriodDtype, ser[i] = tdnat coerces instead of raising,
947
+ # so for consistency, ser[mask] = tdnat must as well
948
+ expected = obj.astype(object).where(mask, tdnat)
949
+ result = obj.where(mask, tdnat)
950
+ tm.assert_equal(result, expected)
951
+
952
+ expected = obj.astype(object).mask(mask, tdnat)
953
+ result = obj.mask(mask, tdnat)
954
+ tm.assert_equal(result, expected)
955
+
956
+ with tm.assert_produces_warning(
957
+ FutureWarning, match="Setting an item of incompatible dtype"
958
+ ):
959
+ obj.mask(mask, tdnat, inplace=True)
960
+ tm.assert_equal(obj, expected)
961
+
962
+
963
+ def test_where_nullable_invalid_na(frame_or_series, any_numeric_ea_dtype):
964
+ # GH#44697
965
+ arr = pd.array([1, 2, 3], dtype=any_numeric_ea_dtype)
966
+ obj = frame_or_series(arr)
967
+
968
+ mask = np.array([True, True, False], ndmin=obj.ndim).T
969
+
970
+ msg = r"Invalid value '.*' for dtype (U?Int|Float)\d{1,2}"
971
+
972
+ for null in tm.NP_NAT_OBJECTS + [pd.NaT]:
973
+ # NaT is an NA value that we should *not* cast to pd.NA dtype
974
+ with pytest.raises(TypeError, match=msg):
975
+ obj.where(mask, null)
976
+
977
+ with pytest.raises(TypeError, match=msg):
978
+ obj.mask(mask, null)
979
+
980
+
981
+ @given(data=OPTIONAL_ONE_OF_ALL)
982
+ def test_where_inplace_casting(data):
983
+ # GH 22051
984
+ df = DataFrame({"a": data})
985
+ df_copy = df.where(pd.notnull(df), None).copy()
986
+ df.where(pd.notnull(df), None, inplace=True)
987
+ tm.assert_equal(df, df_copy)
988
+
989
+
990
+ def test_where_downcast_to_td64():
991
+ ser = Series([1, 2, 3])
992
+
993
+ mask = np.array([False, False, False])
994
+
995
+ td = pd.Timedelta(days=1)
996
+
997
+ msg = "Downcasting behavior in Series and DataFrame methods 'where'"
998
+ with tm.assert_produces_warning(FutureWarning, match=msg):
999
+ res = ser.where(mask, td)
1000
+ expected = Series([td, td, td], dtype="m8[ns]")
1001
+ tm.assert_series_equal(res, expected)
1002
+
1003
+ with pd.option_context("future.no_silent_downcasting", True):
1004
+ with tm.assert_produces_warning(None, match=msg):
1005
+ res2 = ser.where(mask, td)
1006
+ expected2 = expected.astype(object)
1007
+ tm.assert_series_equal(res2, expected2)
1008
+
1009
+
1010
+ def _check_where_equivalences(df, mask, other, expected):
1011
+ # similar to tests.series.indexing.test_setitem.SetitemCastingEquivalences
1012
+ # but with DataFrame in mind and less fleshed-out
1013
+ res = df.where(mask, other)
1014
+ tm.assert_frame_equal(res, expected)
1015
+
1016
+ res = df.mask(~mask, other)
1017
+ tm.assert_frame_equal(res, expected)
1018
+
1019
+ # Note: frame.mask(~mask, other, inplace=True) takes some more work bc
1020
+ # Block.putmask does *not* downcast. The change to 'expected' here
1021
+ # is specific to the cases in test_where_dt64_2d.
1022
+ df = df.copy()
1023
+ df.mask(~mask, other, inplace=True)
1024
+ if not mask.all():
1025
+ # with mask.all(), Block.putmask is a no-op, so does not downcast
1026
+ expected = expected.copy()
1027
+ expected["A"] = expected["A"].astype(object)
1028
+ tm.assert_frame_equal(df, expected)
1029
+
1030
+
1031
+ def test_where_dt64_2d():
1032
+ dti = date_range("2016-01-01", periods=6)
1033
+ dta = dti._data.reshape(3, 2)
1034
+ other = dta - dta[0, 0]
1035
+
1036
+ df = DataFrame(dta, columns=["A", "B"])
1037
+
1038
+ mask = np.asarray(df.isna()).copy()
1039
+ mask[:, 1] = True
1040
+
1041
+ # setting all of one column, none of the other
1042
+ expected = DataFrame({"A": other[:, 0], "B": dta[:, 1]})
1043
+ with tm.assert_produces_warning(
1044
+ FutureWarning, match="Setting an item of incompatible dtype"
1045
+ ):
1046
+ _check_where_equivalences(df, mask, other, expected)
1047
+
1048
+ # setting part of one column, none of the other
1049
+ mask[1, 0] = True
1050
+ expected = DataFrame(
1051
+ {
1052
+ "A": np.array([other[0, 0], dta[1, 0], other[2, 0]], dtype=object),
1053
+ "B": dta[:, 1],
1054
+ }
1055
+ )
1056
+ with tm.assert_produces_warning(
1057
+ FutureWarning, match="Setting an item of incompatible dtype"
1058
+ ):
1059
+ _check_where_equivalences(df, mask, other, expected)
1060
+
1061
+ # setting nothing in either column
1062
+ mask[:] = True
1063
+ expected = df
1064
+ _check_where_equivalences(df, mask, other, expected)
1065
+
1066
+
1067
+ def test_where_producing_ea_cond_for_np_dtype():
1068
+ # GH#44014
1069
+ df = DataFrame({"a": Series([1, pd.NA, 2], dtype="Int64"), "b": [1, 2, 3]})
1070
+ result = df.where(lambda x: x.apply(lambda y: y > 1, axis=1))
1071
+ expected = DataFrame(
1072
+ {"a": Series([pd.NA, pd.NA, 2], dtype="Int64"), "b": [np.nan, 2, 3]}
1073
+ )
1074
+ tm.assert_frame_equal(result, expected)
1075
+
1076
+
1077
+ @pytest.mark.parametrize(
1078
+ "replacement", [0.001, True, "snake", None, datetime(2022, 5, 4)]
1079
+ )
1080
+ def test_where_int_overflow(replacement, using_infer_string, request):
1081
+ # GH 31687
1082
+ df = DataFrame([[1.0, 2e25, "nine"], [np.nan, 0.1, None]])
1083
+ if using_infer_string and replacement not in (None, "snake"):
1084
+ request.node.add_marker(
1085
+ pytest.mark.xfail(reason="Can't set non-string into string column")
1086
+ )
1087
+ result = df.where(pd.notnull(df), replacement)
1088
+ expected = DataFrame([[1.0, 2e25, "nine"], [replacement, 0.1, replacement]])
1089
+
1090
+ tm.assert_frame_equal(result, expected)
1091
+
1092
+
1093
+ def test_where_inplace_no_other():
1094
+ # GH#51685
1095
+ df = DataFrame({"a": [1.0, 2.0], "b": ["x", "y"]})
1096
+ cond = DataFrame({"a": [True, False], "b": [False, True]})
1097
+ df.where(cond, inplace=True)
1098
+ expected = DataFrame({"a": [1, np.nan], "b": [np.nan, "y"]})
1099
+ tm.assert_frame_equal(df, expected)