test_chaining_and_caching.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. from string import ascii_letters as letters
  2. import numpy as np
  3. import pytest
  4. from pandas.errors import (
  5. SettingWithCopyError,
  6. SettingWithCopyWarning,
  7. )
  8. import pandas.util._test_decorators as td
  9. import pandas as pd
  10. from pandas import (
  11. DataFrame,
  12. Series,
  13. Timestamp,
  14. date_range,
  15. option_context,
  16. )
  17. import pandas._testing as tm
  18. msg = "A value is trying to be set on a copy of a slice from a DataFrame"
  19. def random_text(nobs=100):
  20. # Construct a DataFrame where each row is a random slice from 'letters'
  21. idxs = np.random.randint(len(letters), size=(nobs, 2))
  22. idxs.sort(axis=1)
  23. strings = [letters[x[0] : x[1]] for x in idxs]
  24. return DataFrame(strings, columns=["letters"])
  25. class TestCaching:
  26. def test_slice_consolidate_invalidate_item_cache(self, using_copy_on_write):
  27. # this is chained assignment, but will 'work'
  28. with option_context("chained_assignment", None):
  29. # #3970
  30. df = DataFrame({"aa": np.arange(5), "bb": [2.2] * 5})
  31. # Creates a second float block
  32. df["cc"] = 0.0
  33. # caches a reference to the 'bb' series
  34. df["bb"]
  35. # repr machinery triggers consolidation
  36. repr(df)
  37. # Assignment to wrong series
  38. if using_copy_on_write:
  39. with tm.raises_chained_assignment_error():
  40. df["bb"].iloc[0] = 0.17
  41. else:
  42. df["bb"].iloc[0] = 0.17
  43. df._clear_item_cache()
  44. if not using_copy_on_write:
  45. tm.assert_almost_equal(df["bb"][0], 0.17)
  46. else:
  47. # with ArrayManager, parent is not mutated with chained assignment
  48. tm.assert_almost_equal(df["bb"][0], 2.2)
  49. @pytest.mark.parametrize("do_ref", [True, False])
  50. def test_setitem_cache_updating(self, do_ref):
  51. # GH 5424
  52. cont = ["one", "two", "three", "four", "five", "six", "seven"]
  53. df = DataFrame({"a": cont, "b": cont[3:] + cont[:3], "c": np.arange(7)})
  54. # ref the cache
  55. if do_ref:
  56. df.loc[0, "c"]
  57. # set it
  58. df.loc[7, "c"] = 1
  59. assert df.loc[0, "c"] == 0.0
  60. assert df.loc[7, "c"] == 1.0
  61. def test_setitem_cache_updating_slices(self, using_copy_on_write):
  62. # GH 7084
  63. # not updating cache on series setting with slices
  64. expected = DataFrame(
  65. {"A": [600, 600, 600]}, index=date_range("5/7/2014", "5/9/2014")
  66. )
  67. out = DataFrame({"A": [0, 0, 0]}, index=date_range("5/7/2014", "5/9/2014"))
  68. df = DataFrame({"C": ["A", "A", "A"], "D": [100, 200, 300]})
  69. # loop through df to update out
  70. six = Timestamp("5/7/2014")
  71. eix = Timestamp("5/9/2014")
  72. for ix, row in df.iterrows():
  73. out.loc[six:eix, row["C"]] = out.loc[six:eix, row["C"]] + row["D"]
  74. tm.assert_frame_equal(out, expected)
  75. tm.assert_series_equal(out["A"], expected["A"])
  76. # try via a chain indexing
  77. # this actually works
  78. out = DataFrame({"A": [0, 0, 0]}, index=date_range("5/7/2014", "5/9/2014"))
  79. out_original = out.copy()
  80. for ix, row in df.iterrows():
  81. v = out[row["C"]][six:eix] + row["D"]
  82. if using_copy_on_write:
  83. with tm.raises_chained_assignment_error():
  84. out[row["C"]][six:eix] = v
  85. else:
  86. out[row["C"]][six:eix] = v
  87. if not using_copy_on_write:
  88. tm.assert_frame_equal(out, expected)
  89. tm.assert_series_equal(out["A"], expected["A"])
  90. else:
  91. tm.assert_frame_equal(out, out_original)
  92. tm.assert_series_equal(out["A"], out_original["A"])
  93. out = DataFrame({"A": [0, 0, 0]}, index=date_range("5/7/2014", "5/9/2014"))
  94. for ix, row in df.iterrows():
  95. out.loc[six:eix, row["C"]] += row["D"]
  96. tm.assert_frame_equal(out, expected)
  97. tm.assert_series_equal(out["A"], expected["A"])
  98. def test_altering_series_clears_parent_cache(self, using_copy_on_write):
  99. # GH #33675
  100. df = DataFrame([[1, 2], [3, 4]], index=["a", "b"], columns=["A", "B"])
  101. ser = df["A"]
  102. if using_copy_on_write:
  103. assert "A" not in df._item_cache
  104. else:
  105. assert "A" in df._item_cache
  106. # Adding a new entry to ser swaps in a new array, so "A" needs to
  107. # be removed from df._item_cache
  108. ser["c"] = 5
  109. assert len(ser) == 3
  110. assert "A" not in df._item_cache
  111. assert df["A"] is not ser
  112. assert len(df["A"]) == 2
  113. class TestChaining:
  114. def test_setitem_chained_setfault(self, using_copy_on_write):
  115. # GH6026
  116. data = ["right", "left", "left", "left", "right", "left", "timeout"]
  117. mdata = ["right", "left", "left", "left", "right", "left", "none"]
  118. df = DataFrame({"response": np.array(data)})
  119. mask = df.response == "timeout"
  120. if using_copy_on_write:
  121. with tm.raises_chained_assignment_error():
  122. df.response[mask] = "none"
  123. tm.assert_frame_equal(df, DataFrame({"response": data}))
  124. else:
  125. df.response[mask] = "none"
  126. tm.assert_frame_equal(df, DataFrame({"response": mdata}))
  127. recarray = np.rec.fromarrays([data], names=["response"])
  128. df = DataFrame(recarray)
  129. mask = df.response == "timeout"
  130. if using_copy_on_write:
  131. with tm.raises_chained_assignment_error():
  132. df.response[mask] = "none"
  133. tm.assert_frame_equal(df, DataFrame({"response": data}))
  134. else:
  135. df.response[mask] = "none"
  136. tm.assert_frame_equal(df, DataFrame({"response": mdata}))
  137. df = DataFrame({"response": data, "response1": data})
  138. df_original = df.copy()
  139. mask = df.response == "timeout"
  140. if using_copy_on_write:
  141. with tm.raises_chained_assignment_error():
  142. df.response[mask] = "none"
  143. tm.assert_frame_equal(df, df_original)
  144. else:
  145. df.response[mask] = "none"
  146. tm.assert_frame_equal(df, DataFrame({"response": mdata, "response1": data}))
  147. # GH 6056
  148. expected = DataFrame({"A": [np.nan, "bar", "bah", "foo", "bar"]})
  149. df = DataFrame({"A": np.array(["foo", "bar", "bah", "foo", "bar"])})
  150. if using_copy_on_write:
  151. with tm.raises_chained_assignment_error():
  152. df["A"].iloc[0] = np.nan
  153. expected = DataFrame({"A": ["foo", "bar", "bah", "foo", "bar"]})
  154. else:
  155. df["A"].iloc[0] = np.nan
  156. expected = DataFrame({"A": [np.nan, "bar", "bah", "foo", "bar"]})
  157. result = df.head()
  158. tm.assert_frame_equal(result, expected)
  159. df = DataFrame({"A": np.array(["foo", "bar", "bah", "foo", "bar"])})
  160. if using_copy_on_write:
  161. with tm.raises_chained_assignment_error():
  162. df.A.iloc[0] = np.nan
  163. else:
  164. df.A.iloc[0] = np.nan
  165. result = df.head()
  166. tm.assert_frame_equal(result, expected)
  167. @pytest.mark.arm_slow
  168. def test_detect_chained_assignment(self, using_copy_on_write):
  169. with option_context("chained_assignment", "raise"):
  170. # work with the chain
  171. expected = DataFrame([[-5, 1], [-6, 3]], columns=list("AB"))
  172. df = DataFrame(
  173. np.arange(4).reshape(2, 2), columns=list("AB"), dtype="int64"
  174. )
  175. df_original = df.copy()
  176. assert df._is_copy is None
  177. if using_copy_on_write:
  178. with tm.raises_chained_assignment_error():
  179. df["A"][0] = -5
  180. with tm.raises_chained_assignment_error():
  181. df["A"][1] = -6
  182. tm.assert_frame_equal(df, df_original)
  183. else:
  184. df["A"][0] = -5
  185. df["A"][1] = -6
  186. tm.assert_frame_equal(df, expected)
  187. @pytest.mark.arm_slow
  188. def test_detect_chained_assignment_raises(
  189. self, using_array_manager, using_copy_on_write
  190. ):
  191. # test with the chaining
  192. df = DataFrame(
  193. {
  194. "A": Series(range(2), dtype="int64"),
  195. "B": np.array(np.arange(2, 4), dtype=np.float64),
  196. }
  197. )
  198. df_original = df.copy()
  199. assert df._is_copy is None
  200. if using_copy_on_write:
  201. with tm.raises_chained_assignment_error():
  202. df["A"][0] = -5
  203. with tm.raises_chained_assignment_error():
  204. df["A"][1] = -6
  205. tm.assert_frame_equal(df, df_original)
  206. elif not using_array_manager:
  207. with pytest.raises(SettingWithCopyError, match=msg):
  208. df["A"][0] = -5
  209. with pytest.raises(SettingWithCopyError, match=msg):
  210. df["A"][1] = np.nan
  211. assert df["A"]._is_copy is None
  212. else:
  213. # INFO(ArrayManager) for ArrayManager it doesn't matter that it's
  214. # a mixed dataframe
  215. df["A"][0] = -5
  216. df["A"][1] = -6
  217. expected = DataFrame([[-5, 2], [-6, 3]], columns=list("AB"))
  218. expected["B"] = expected["B"].astype("float64")
  219. tm.assert_frame_equal(df, expected)
  220. @pytest.mark.arm_slow
  221. def test_detect_chained_assignment_fails(self, using_copy_on_write):
  222. # Using a copy (the chain), fails
  223. df = DataFrame(
  224. {
  225. "A": Series(range(2), dtype="int64"),
  226. "B": np.array(np.arange(2, 4), dtype=np.float64),
  227. }
  228. )
  229. if using_copy_on_write:
  230. with tm.raises_chained_assignment_error():
  231. df.loc[0]["A"] = -5
  232. else:
  233. with pytest.raises(SettingWithCopyError, match=msg):
  234. df.loc[0]["A"] = -5
  235. @pytest.mark.arm_slow
  236. def test_detect_chained_assignment_doc_example(self, using_copy_on_write):
  237. # Doc example
  238. df = DataFrame(
  239. {
  240. "a": ["one", "one", "two", "three", "two", "one", "six"],
  241. "c": Series(range(7), dtype="int64"),
  242. }
  243. )
  244. assert df._is_copy is None
  245. if using_copy_on_write:
  246. indexer = df.a.str.startswith("o")
  247. with tm.raises_chained_assignment_error():
  248. df[indexer]["c"] = 42
  249. else:
  250. with pytest.raises(SettingWithCopyError, match=msg):
  251. indexer = df.a.str.startswith("o")
  252. df[indexer]["c"] = 42
  253. @pytest.mark.arm_slow
  254. def test_detect_chained_assignment_object_dtype(
  255. self, using_array_manager, using_copy_on_write
  256. ):
  257. expected = DataFrame({"A": [111, "bbb", "ccc"], "B": [1, 2, 3]})
  258. df = DataFrame({"A": ["aaa", "bbb", "ccc"], "B": [1, 2, 3]})
  259. df_original = df.copy()
  260. if not using_copy_on_write:
  261. with pytest.raises(SettingWithCopyError, match=msg):
  262. df.loc[0]["A"] = 111
  263. if using_copy_on_write:
  264. with tm.raises_chained_assignment_error():
  265. df["A"][0] = 111
  266. tm.assert_frame_equal(df, df_original)
  267. elif not using_array_manager:
  268. with pytest.raises(SettingWithCopyError, match=msg):
  269. df["A"][0] = 111
  270. df.loc[0, "A"] = 111
  271. tm.assert_frame_equal(df, expected)
  272. else:
  273. # INFO(ArrayManager) for ArrayManager it doesn't matter that it's
  274. # a mixed dataframe
  275. df["A"][0] = 111
  276. tm.assert_frame_equal(df, expected)
  277. @pytest.mark.arm_slow
  278. def test_detect_chained_assignment_is_copy_pickle(self):
  279. # gh-5475: Make sure that is_copy is picked up reconstruction
  280. df = DataFrame({"A": [1, 2]})
  281. assert df._is_copy is None
  282. with tm.ensure_clean("__tmp__pickle") as path:
  283. df.to_pickle(path)
  284. df2 = pd.read_pickle(path)
  285. df2["B"] = df2["A"]
  286. df2["B"] = df2["A"]
  287. @pytest.mark.arm_slow
  288. def test_detect_chained_assignment_setting_entire_column(self):
  289. # gh-5597: a spurious raise as we are setting the entire column here
  290. df = random_text(100000)
  291. # Always a copy
  292. x = df.iloc[[0, 1, 2]]
  293. assert x._is_copy is not None
  294. x = df.iloc[[0, 1, 2, 4]]
  295. assert x._is_copy is not None
  296. # Explicitly copy
  297. indexer = df.letters.apply(lambda x: len(x) > 10)
  298. df = df.loc[indexer].copy()
  299. assert df._is_copy is None
  300. df["letters"] = df["letters"].apply(str.lower)
  301. @pytest.mark.arm_slow
  302. def test_detect_chained_assignment_implicit_take(self):
  303. # Implicitly take
  304. df = random_text(100000)
  305. indexer = df.letters.apply(lambda x: len(x) > 10)
  306. df = df.loc[indexer]
  307. assert df._is_copy is not None
  308. df["letters"] = df["letters"].apply(str.lower)
  309. @pytest.mark.arm_slow
  310. def test_detect_chained_assignment_implicit_take2(self, using_copy_on_write):
  311. if using_copy_on_write:
  312. pytest.skip("_is_copy is not always set for CoW")
  313. # Implicitly take 2
  314. df = random_text(100000)
  315. indexer = df.letters.apply(lambda x: len(x) > 10)
  316. df = df.loc[indexer]
  317. assert df._is_copy is not None
  318. df.loc[:, "letters"] = df["letters"].apply(str.lower)
  319. # with the enforcement of #45333 in 2.0, the .loc[:, letters] setting
  320. # is inplace, so df._is_copy remains non-None.
  321. assert df._is_copy is not None
  322. df["letters"] = df["letters"].apply(str.lower)
  323. assert df._is_copy is None
  324. @pytest.mark.arm_slow
  325. def test_detect_chained_assignment_str(self):
  326. df = random_text(100000)
  327. indexer = df.letters.apply(lambda x: len(x) > 10)
  328. df.loc[indexer, "letters"] = df.loc[indexer, "letters"].apply(str.lower)
  329. @pytest.mark.arm_slow
  330. def test_detect_chained_assignment_is_copy(self):
  331. # an identical take, so no copy
  332. df = DataFrame({"a": [1]}).dropna()
  333. assert df._is_copy is None
  334. df["a"] += 1
  335. @pytest.mark.arm_slow
  336. def test_detect_chained_assignment_sorting(self):
  337. df = DataFrame(np.random.randn(10, 4))
  338. ser = df.iloc[:, 0].sort_values()
  339. tm.assert_series_equal(ser, df.iloc[:, 0].sort_values())
  340. tm.assert_series_equal(ser, df[0].sort_values())
  341. @pytest.mark.arm_slow
  342. def test_detect_chained_assignment_false_positives(self):
  343. # see gh-6025: false positives
  344. df = DataFrame({"column1": ["a", "a", "a"], "column2": [4, 8, 9]})
  345. str(df)
  346. df["column1"] = df["column1"] + "b"
  347. str(df)
  348. df = df[df["column2"] != 8]
  349. str(df)
  350. df["column1"] = df["column1"] + "c"
  351. str(df)
  352. @pytest.mark.arm_slow
  353. def test_detect_chained_assignment_undefined_column(self, using_copy_on_write):
  354. # from SO:
  355. # https://stackoverflow.com/questions/24054495/potential-bug-setting-value-for-undefined-column-using-iloc
  356. df = DataFrame(np.arange(0, 9), columns=["count"])
  357. df["group"] = "b"
  358. df_original = df.copy()
  359. if using_copy_on_write:
  360. with tm.raises_chained_assignment_error():
  361. df.iloc[0:5]["group"] = "a"
  362. tm.assert_frame_equal(df, df_original)
  363. else:
  364. with pytest.raises(SettingWithCopyError, match=msg):
  365. df.iloc[0:5]["group"] = "a"
  366. @pytest.mark.arm_slow
  367. def test_detect_chained_assignment_changing_dtype(
  368. self, using_array_manager, using_copy_on_write
  369. ):
  370. # Mixed type setting but same dtype & changing dtype
  371. df = DataFrame(
  372. {
  373. "A": date_range("20130101", periods=5),
  374. "B": np.random.randn(5),
  375. "C": np.arange(5, dtype="int64"),
  376. "D": ["a", "b", "c", "d", "e"],
  377. }
  378. )
  379. df_original = df.copy()
  380. if using_copy_on_write:
  381. with tm.raises_chained_assignment_error():
  382. df.loc[2]["D"] = "foo"
  383. with tm.raises_chained_assignment_error():
  384. df.loc[2]["C"] = "foo"
  385. with tm.raises_chained_assignment_error():
  386. df["C"][2] = "foo"
  387. tm.assert_frame_equal(df, df_original)
  388. if not using_copy_on_write:
  389. with pytest.raises(SettingWithCopyError, match=msg):
  390. df.loc[2]["D"] = "foo"
  391. with pytest.raises(SettingWithCopyError, match=msg):
  392. df.loc[2]["C"] = "foo"
  393. if not using_array_manager:
  394. with pytest.raises(SettingWithCopyError, match=msg):
  395. df["C"][2] = "foo"
  396. else:
  397. # INFO(ArrayManager) for ArrayManager it doesn't matter if it's
  398. # changing the dtype or not
  399. df["C"][2] = "foo"
  400. assert df.loc[2, "C"] == "foo"
  401. def test_setting_with_copy_bug(self, using_copy_on_write):
  402. # operating on a copy
  403. df = DataFrame(
  404. {"a": list(range(4)), "b": list("ab.."), "c": ["a", "b", np.nan, "d"]}
  405. )
  406. df_original = df.copy()
  407. mask = pd.isna(df.c)
  408. if using_copy_on_write:
  409. with tm.raises_chained_assignment_error():
  410. df[["c"]][mask] = df[["b"]][mask]
  411. tm.assert_frame_equal(df, df_original)
  412. else:
  413. with pytest.raises(SettingWithCopyError, match=msg):
  414. df[["c"]][mask] = df[["b"]][mask]
  415. def test_setting_with_copy_bug_no_warning(self):
  416. # invalid warning as we are returning a new object
  417. # GH 8730
  418. df1 = DataFrame({"x": Series(["a", "b", "c"]), "y": Series(["d", "e", "f"])})
  419. df2 = df1[["x"]]
  420. # this should not raise
  421. df2["y"] = ["g", "h", "i"]
  422. def test_detect_chained_assignment_warnings_errors(self, using_copy_on_write):
  423. df = DataFrame({"A": ["aaa", "bbb", "ccc"], "B": [1, 2, 3]})
  424. if using_copy_on_write:
  425. with tm.raises_chained_assignment_error():
  426. df.loc[0]["A"] = 111
  427. return
  428. with option_context("chained_assignment", "warn"):
  429. with tm.assert_produces_warning(SettingWithCopyWarning):
  430. df.loc[0]["A"] = 111
  431. with option_context("chained_assignment", "raise"):
  432. with pytest.raises(SettingWithCopyError, match=msg):
  433. df.loc[0]["A"] = 111
  434. @pytest.mark.parametrize("rhs", [3, DataFrame({0: [1, 2, 3, 4]})])
  435. def test_detect_chained_assignment_warning_stacklevel(
  436. self, rhs, using_copy_on_write
  437. ):
  438. # GH#42570
  439. df = DataFrame(np.arange(25).reshape(5, 5))
  440. df_original = df.copy()
  441. chained = df.loc[:3]
  442. with option_context("chained_assignment", "warn"):
  443. if not using_copy_on_write:
  444. with tm.assert_produces_warning(SettingWithCopyWarning) as t:
  445. chained[2] = rhs
  446. assert t[0].filename == __file__
  447. else:
  448. # INFO(CoW) no warning, and original dataframe not changed
  449. with tm.assert_produces_warning(None):
  450. chained[2] = rhs
  451. tm.assert_frame_equal(df, df_original)
  452. # TODO(ArrayManager) fast_xs with array-like scalars is not yet working
  453. @td.skip_array_manager_not_yet_implemented
  454. def test_chained_getitem_with_lists(self):
  455. # GH6394
  456. # Regression in chained getitem indexing with embedded list-like from
  457. # 0.12
  458. df = DataFrame({"A": 5 * [np.zeros(3)], "B": 5 * [np.ones(3)]})
  459. expected = df["A"].iloc[2]
  460. result = df.loc[2, "A"]
  461. tm.assert_numpy_array_equal(result, expected)
  462. result2 = df.iloc[2]["A"]
  463. tm.assert_numpy_array_equal(result2, expected)
  464. result3 = df["A"].loc[2]
  465. tm.assert_numpy_array_equal(result3, expected)
  466. result4 = df["A"].iloc[2]
  467. tm.assert_numpy_array_equal(result4, expected)
  468. def test_cache_updating(self):
  469. # GH 4939, make sure to update the cache on setitem
  470. df = tm.makeDataFrame()
  471. df["A"] # cache series
  472. df.loc["Hello Friend"] = df.iloc[0]
  473. assert "Hello Friend" in df["A"].index
  474. assert "Hello Friend" in df["B"].index
  475. def test_cache_updating2(self, using_copy_on_write):
  476. # 10264
  477. df = DataFrame(
  478. np.zeros((5, 5), dtype="int64"),
  479. columns=["a", "b", "c", "d", "e"],
  480. index=range(5),
  481. )
  482. df["f"] = 0
  483. df_orig = df.copy()
  484. if using_copy_on_write:
  485. with pytest.raises(ValueError, match="read-only"):
  486. df.f.values[3] = 1
  487. tm.assert_frame_equal(df, df_orig)
  488. return
  489. df.f.values[3] = 1
  490. df.f.values[3] = 2
  491. expected = DataFrame(
  492. np.zeros((5, 6), dtype="int64"),
  493. columns=["a", "b", "c", "d", "e", "f"],
  494. index=range(5),
  495. )
  496. expected.at[3, "f"] = 2
  497. tm.assert_frame_equal(df, expected)
  498. expected = Series([0, 0, 0, 2, 0], name="f")
  499. tm.assert_series_equal(df.f, expected)
  500. def test_iloc_setitem_chained_assignment(self, using_copy_on_write):
  501. # GH#3970
  502. with option_context("chained_assignment", None):
  503. df = DataFrame({"aa": range(5), "bb": [2.2] * 5})
  504. df["cc"] = 0.0
  505. ck = [True] * len(df)
  506. if using_copy_on_write:
  507. with tm.raises_chained_assignment_error():
  508. df["bb"].iloc[0] = 0.13
  509. else:
  510. df["bb"].iloc[0] = 0.13
  511. # GH#3970 this lookup used to break the chained setting to 0.15
  512. df.iloc[ck]
  513. if using_copy_on_write:
  514. with tm.raises_chained_assignment_error():
  515. df["bb"].iloc[0] = 0.15
  516. else:
  517. df["bb"].iloc[0] = 0.15
  518. if not using_copy_on_write:
  519. assert df["bb"].iloc[0] == 0.15
  520. else:
  521. assert df["bb"].iloc[0] == 2.2
  522. def test_getitem_loc_assignment_slice_state(self, using_copy_on_write):
  523. # GH 13569
  524. df = DataFrame({"a": [10, 20, 30]})
  525. if using_copy_on_write:
  526. with tm.raises_chained_assignment_error():
  527. df["a"].loc[4] = 40
  528. else:
  529. df["a"].loc[4] = 40
  530. tm.assert_frame_equal(df, DataFrame({"a": [10, 20, 30]}))
  531. tm.assert_series_equal(df["a"], Series([10, 20, 30], name="a"))