test_iloc.py 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435
  1. """ test positional based indexing with iloc """
  2. from datetime import datetime
  3. import re
  4. from warnings import (
  5. catch_warnings,
  6. simplefilter,
  7. )
  8. import numpy as np
  9. import pytest
  10. from pandas.errors import IndexingError
  11. import pandas.util._test_decorators as td
  12. from pandas import (
  13. NA,
  14. Categorical,
  15. CategoricalDtype,
  16. DataFrame,
  17. Index,
  18. Interval,
  19. NaT,
  20. Series,
  21. Timestamp,
  22. array,
  23. concat,
  24. date_range,
  25. interval_range,
  26. isna,
  27. to_datetime,
  28. )
  29. import pandas._testing as tm
  30. from pandas.api.types import is_scalar
  31. from pandas.tests.indexing.common import check_indexing_smoketest_or_raises
  32. # We pass through the error message from numpy
  33. _slice_iloc_msg = re.escape(
  34. "only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) "
  35. "and integer or boolean arrays are valid indices"
  36. )
  37. class TestiLoc:
  38. @pytest.mark.parametrize("key", [2, -1, [0, 1, 2]])
  39. @pytest.mark.parametrize("kind", ["series", "frame"])
  40. @pytest.mark.parametrize(
  41. "col",
  42. ["labels", "mixed", "ts", "floats", "empty"],
  43. )
  44. def test_iloc_getitem_int_and_list_int(self, key, kind, col, request):
  45. obj = request.getfixturevalue(f"{kind}_{col}")
  46. check_indexing_smoketest_or_raises(
  47. obj,
  48. "iloc",
  49. key,
  50. fails=IndexError,
  51. )
  52. # array of ints (GH5006), make sure that a single indexer is returning
  53. # the correct type
  54. class TestiLocBaseIndependent:
  55. """Tests Independent Of Base Class"""
  56. @pytest.mark.parametrize(
  57. "key",
  58. [
  59. slice(None),
  60. slice(3),
  61. range(3),
  62. [0, 1, 2],
  63. Index(range(3)),
  64. np.asarray([0, 1, 2]),
  65. ],
  66. )
  67. @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
  68. def test_iloc_setitem_fullcol_categorical(self, indexer, key, using_array_manager):
  69. frame = DataFrame({0: range(3)}, dtype=object)
  70. cat = Categorical(["alpha", "beta", "gamma"])
  71. if not using_array_manager:
  72. assert frame._mgr.blocks[0]._can_hold_element(cat)
  73. df = frame.copy()
  74. orig_vals = df.values
  75. indexer(df)[key, 0] = cat
  76. expected = DataFrame({0: cat}).astype(object)
  77. if not using_array_manager:
  78. assert np.shares_memory(df[0].values, orig_vals)
  79. tm.assert_frame_equal(df, expected)
  80. # check we dont have a view on cat (may be undesired GH#39986)
  81. df.iloc[0, 0] = "gamma"
  82. assert cat[0] != "gamma"
  83. # pre-2.0 with mixed dataframe ("split" path) we always overwrote the
  84. # column. as of 2.0 we correctly write "into" the column, so
  85. # we retain the object dtype.
  86. frame = DataFrame({0: np.array([0, 1, 2], dtype=object), 1: range(3)})
  87. df = frame.copy()
  88. orig_vals = df.values
  89. indexer(df)[key, 0] = cat
  90. expected = DataFrame({0: cat.astype(object), 1: range(3)})
  91. tm.assert_frame_equal(df, expected)
  92. @pytest.mark.parametrize("box", [array, Series])
  93. def test_iloc_setitem_ea_inplace(self, frame_or_series, box, using_copy_on_write):
  94. # GH#38952 Case with not setting a full column
  95. # IntegerArray without NAs
  96. arr = array([1, 2, 3, 4])
  97. obj = frame_or_series(arr.to_numpy("i8"))
  98. if frame_or_series is Series:
  99. values = obj.values
  100. else:
  101. values = obj._mgr.arrays[0]
  102. if frame_or_series is Series:
  103. obj.iloc[:2] = box(arr[2:])
  104. else:
  105. obj.iloc[:2, 0] = box(arr[2:])
  106. expected = frame_or_series(np.array([3, 4, 3, 4], dtype="i8"))
  107. tm.assert_equal(obj, expected)
  108. # Check that we are actually in-place
  109. if frame_or_series is Series:
  110. if using_copy_on_write:
  111. assert obj.values is not values
  112. assert np.shares_memory(obj.values, values)
  113. else:
  114. assert obj.values is values
  115. else:
  116. assert np.shares_memory(obj[0].values, values)
  117. def test_is_scalar_access(self):
  118. # GH#32085 index with duplicates doesn't matter for _is_scalar_access
  119. index = Index([1, 2, 1])
  120. ser = Series(range(3), index=index)
  121. assert ser.iloc._is_scalar_access((1,))
  122. df = ser.to_frame()
  123. assert df.iloc._is_scalar_access((1, 0))
  124. def test_iloc_exceeds_bounds(self):
  125. # GH6296
  126. # iloc should allow indexers that exceed the bounds
  127. df = DataFrame(np.random.random_sample((20, 5)), columns=list("ABCDE"))
  128. # lists of positions should raise IndexError!
  129. msg = "positional indexers are out-of-bounds"
  130. with pytest.raises(IndexError, match=msg):
  131. df.iloc[:, [0, 1, 2, 3, 4, 5]]
  132. with pytest.raises(IndexError, match=msg):
  133. df.iloc[[1, 30]]
  134. with pytest.raises(IndexError, match=msg):
  135. df.iloc[[1, -30]]
  136. with pytest.raises(IndexError, match=msg):
  137. df.iloc[[100]]
  138. s = df["A"]
  139. with pytest.raises(IndexError, match=msg):
  140. s.iloc[[100]]
  141. with pytest.raises(IndexError, match=msg):
  142. s.iloc[[-100]]
  143. # still raise on a single indexer
  144. msg = "single positional indexer is out-of-bounds"
  145. with pytest.raises(IndexError, match=msg):
  146. df.iloc[30]
  147. with pytest.raises(IndexError, match=msg):
  148. df.iloc[-30]
  149. # GH10779
  150. # single positive/negative indexer exceeding Series bounds should raise
  151. # an IndexError
  152. with pytest.raises(IndexError, match=msg):
  153. s.iloc[30]
  154. with pytest.raises(IndexError, match=msg):
  155. s.iloc[-30]
  156. # slices are ok
  157. result = df.iloc[:, 4:10] # 0 < start < len < stop
  158. expected = df.iloc[:, 4:]
  159. tm.assert_frame_equal(result, expected)
  160. result = df.iloc[:, -4:-10] # stop < 0 < start < len
  161. expected = df.iloc[:, :0]
  162. tm.assert_frame_equal(result, expected)
  163. result = df.iloc[:, 10:4:-1] # 0 < stop < len < start (down)
  164. expected = df.iloc[:, :4:-1]
  165. tm.assert_frame_equal(result, expected)
  166. result = df.iloc[:, 4:-10:-1] # stop < 0 < start < len (down)
  167. expected = df.iloc[:, 4::-1]
  168. tm.assert_frame_equal(result, expected)
  169. result = df.iloc[:, -10:4] # start < 0 < stop < len
  170. expected = df.iloc[:, :4]
  171. tm.assert_frame_equal(result, expected)
  172. result = df.iloc[:, 10:4] # 0 < stop < len < start
  173. expected = df.iloc[:, :0]
  174. tm.assert_frame_equal(result, expected)
  175. result = df.iloc[:, -10:-11:-1] # stop < start < 0 < len (down)
  176. expected = df.iloc[:, :0]
  177. tm.assert_frame_equal(result, expected)
  178. result = df.iloc[:, 10:11] # 0 < len < start < stop
  179. expected = df.iloc[:, :0]
  180. tm.assert_frame_equal(result, expected)
  181. # slice bounds exceeding is ok
  182. result = s.iloc[18:30]
  183. expected = s.iloc[18:]
  184. tm.assert_series_equal(result, expected)
  185. result = s.iloc[30:]
  186. expected = s.iloc[:0]
  187. tm.assert_series_equal(result, expected)
  188. result = s.iloc[30::-1]
  189. expected = s.iloc[::-1]
  190. tm.assert_series_equal(result, expected)
  191. # doc example
  192. def check(result, expected):
  193. str(result)
  194. result.dtypes
  195. tm.assert_frame_equal(result, expected)
  196. dfl = DataFrame(np.random.randn(5, 2), columns=list("AB"))
  197. check(dfl.iloc[:, 2:3], DataFrame(index=dfl.index, columns=[]))
  198. check(dfl.iloc[:, 1:3], dfl.iloc[:, [1]])
  199. check(dfl.iloc[4:6], dfl.iloc[[4]])
  200. msg = "positional indexers are out-of-bounds"
  201. with pytest.raises(IndexError, match=msg):
  202. dfl.iloc[[4, 5, 6]]
  203. msg = "single positional indexer is out-of-bounds"
  204. with pytest.raises(IndexError, match=msg):
  205. dfl.iloc[:, 4]
  206. @pytest.mark.parametrize("index,columns", [(np.arange(20), list("ABCDE"))])
  207. @pytest.mark.parametrize(
  208. "index_vals,column_vals",
  209. [
  210. ([slice(None), ["A", "D"]]),
  211. (["1", "2"], slice(None)),
  212. ([datetime(2019, 1, 1)], slice(None)),
  213. ],
  214. )
  215. def test_iloc_non_integer_raises(self, index, columns, index_vals, column_vals):
  216. # GH 25753
  217. df = DataFrame(
  218. np.random.randn(len(index), len(columns)), index=index, columns=columns
  219. )
  220. msg = ".iloc requires numeric indexers, got"
  221. with pytest.raises(IndexError, match=msg):
  222. df.iloc[index_vals, column_vals]
  223. def test_iloc_getitem_invalid_scalar(self, frame_or_series):
  224. # GH 21982
  225. obj = DataFrame(np.arange(100).reshape(10, 10))
  226. obj = tm.get_obj(obj, frame_or_series)
  227. with pytest.raises(TypeError, match="Cannot index by location index"):
  228. obj.iloc["a"]
  229. def test_iloc_array_not_mutating_negative_indices(self):
  230. # GH 21867
  231. array_with_neg_numbers = np.array([1, 2, -1])
  232. array_copy = array_with_neg_numbers.copy()
  233. df = DataFrame(
  234. {"A": [100, 101, 102], "B": [103, 104, 105], "C": [106, 107, 108]},
  235. index=[1, 2, 3],
  236. )
  237. df.iloc[array_with_neg_numbers]
  238. tm.assert_numpy_array_equal(array_with_neg_numbers, array_copy)
  239. df.iloc[:, array_with_neg_numbers]
  240. tm.assert_numpy_array_equal(array_with_neg_numbers, array_copy)
  241. def test_iloc_getitem_neg_int_can_reach_first_index(self):
  242. # GH10547 and GH10779
  243. # negative integers should be able to reach index 0
  244. df = DataFrame({"A": [2, 3, 5], "B": [7, 11, 13]})
  245. s = df["A"]
  246. expected = df.iloc[0]
  247. result = df.iloc[-3]
  248. tm.assert_series_equal(result, expected)
  249. expected = df.iloc[[0]]
  250. result = df.iloc[[-3]]
  251. tm.assert_frame_equal(result, expected)
  252. expected = s.iloc[0]
  253. result = s.iloc[-3]
  254. assert result == expected
  255. expected = s.iloc[[0]]
  256. result = s.iloc[[-3]]
  257. tm.assert_series_equal(result, expected)
  258. # check the length 1 Series case highlighted in GH10547
  259. expected = Series(["a"], index=["A"])
  260. result = expected.iloc[[-1]]
  261. tm.assert_series_equal(result, expected)
  262. def test_iloc_getitem_dups(self):
  263. # GH 6766
  264. df1 = DataFrame([{"A": None, "B": 1}, {"A": 2, "B": 2}])
  265. df2 = DataFrame([{"A": 3, "B": 3}, {"A": 4, "B": 4}])
  266. df = concat([df1, df2], axis=1)
  267. # cross-sectional indexing
  268. result = df.iloc[0, 0]
  269. assert isna(result)
  270. result = df.iloc[0, :]
  271. expected = Series([np.nan, 1, 3, 3], index=["A", "B", "A", "B"], name=0)
  272. tm.assert_series_equal(result, expected)
  273. def test_iloc_getitem_array(self):
  274. df = DataFrame(
  275. [
  276. {"A": 1, "B": 2, "C": 3},
  277. {"A": 100, "B": 200, "C": 300},
  278. {"A": 1000, "B": 2000, "C": 3000},
  279. ]
  280. )
  281. expected = DataFrame([{"A": 1, "B": 2, "C": 3}])
  282. tm.assert_frame_equal(df.iloc[[0]], expected)
  283. expected = DataFrame([{"A": 1, "B": 2, "C": 3}, {"A": 100, "B": 200, "C": 300}])
  284. tm.assert_frame_equal(df.iloc[[0, 1]], expected)
  285. expected = DataFrame([{"B": 2, "C": 3}, {"B": 2000, "C": 3000}], index=[0, 2])
  286. result = df.iloc[[0, 2], [1, 2]]
  287. tm.assert_frame_equal(result, expected)
  288. def test_iloc_getitem_bool(self):
  289. df = DataFrame(
  290. [
  291. {"A": 1, "B": 2, "C": 3},
  292. {"A": 100, "B": 200, "C": 300},
  293. {"A": 1000, "B": 2000, "C": 3000},
  294. ]
  295. )
  296. expected = DataFrame([{"A": 1, "B": 2, "C": 3}, {"A": 100, "B": 200, "C": 300}])
  297. result = df.iloc[[True, True, False]]
  298. tm.assert_frame_equal(result, expected)
  299. expected = DataFrame(
  300. [{"A": 1, "B": 2, "C": 3}, {"A": 1000, "B": 2000, "C": 3000}], index=[0, 2]
  301. )
  302. result = df.iloc[lambda x: x.index % 2 == 0]
  303. tm.assert_frame_equal(result, expected)
  304. @pytest.mark.parametrize("index", [[True, False], [True, False, True, False]])
  305. def test_iloc_getitem_bool_diff_len(self, index):
  306. # GH26658
  307. s = Series([1, 2, 3])
  308. msg = f"Boolean index has wrong length: {len(index)} instead of {len(s)}"
  309. with pytest.raises(IndexError, match=msg):
  310. s.iloc[index]
  311. def test_iloc_getitem_slice(self):
  312. df = DataFrame(
  313. [
  314. {"A": 1, "B": 2, "C": 3},
  315. {"A": 100, "B": 200, "C": 300},
  316. {"A": 1000, "B": 2000, "C": 3000},
  317. ]
  318. )
  319. expected = DataFrame([{"A": 1, "B": 2, "C": 3}, {"A": 100, "B": 200, "C": 300}])
  320. result = df.iloc[:2]
  321. tm.assert_frame_equal(result, expected)
  322. expected = DataFrame([{"A": 100, "B": 200}], index=[1])
  323. result = df.iloc[1:2, 0:2]
  324. tm.assert_frame_equal(result, expected)
  325. expected = DataFrame(
  326. [{"A": 1, "C": 3}, {"A": 100, "C": 300}, {"A": 1000, "C": 3000}]
  327. )
  328. result = df.iloc[:, lambda df: [0, 2]]
  329. tm.assert_frame_equal(result, expected)
  330. def test_iloc_getitem_slice_dups(self):
  331. df1 = DataFrame(np.random.randn(10, 4), columns=["A", "A", "B", "B"])
  332. df2 = DataFrame(
  333. np.random.randint(0, 10, size=20).reshape(10, 2), columns=["A", "C"]
  334. )
  335. # axis=1
  336. df = concat([df1, df2], axis=1)
  337. tm.assert_frame_equal(df.iloc[:, :4], df1)
  338. tm.assert_frame_equal(df.iloc[:, 4:], df2)
  339. df = concat([df2, df1], axis=1)
  340. tm.assert_frame_equal(df.iloc[:, :2], df2)
  341. tm.assert_frame_equal(df.iloc[:, 2:], df1)
  342. exp = concat([df2, df1.iloc[:, [0]]], axis=1)
  343. tm.assert_frame_equal(df.iloc[:, 0:3], exp)
  344. # axis=0
  345. df = concat([df, df], axis=0)
  346. tm.assert_frame_equal(df.iloc[0:10, :2], df2)
  347. tm.assert_frame_equal(df.iloc[0:10, 2:], df1)
  348. tm.assert_frame_equal(df.iloc[10:, :2], df2)
  349. tm.assert_frame_equal(df.iloc[10:, 2:], df1)
  350. def test_iloc_setitem(self):
  351. df = DataFrame(
  352. np.random.randn(4, 4), index=np.arange(0, 8, 2), columns=np.arange(0, 12, 3)
  353. )
  354. df.iloc[1, 1] = 1
  355. result = df.iloc[1, 1]
  356. assert result == 1
  357. df.iloc[:, 2:3] = 0
  358. expected = df.iloc[:, 2:3]
  359. result = df.iloc[:, 2:3]
  360. tm.assert_frame_equal(result, expected)
  361. # GH5771
  362. s = Series(0, index=[4, 5, 6])
  363. s.iloc[1:2] += 1
  364. expected = Series([0, 1, 0], index=[4, 5, 6])
  365. tm.assert_series_equal(s, expected)
  366. def test_iloc_setitem_axis_argument(self):
  367. # GH45032
  368. df = DataFrame([[6, "c", 10], [7, "d", 11], [8, "e", 12]])
  369. expected = DataFrame([[6, "c", 10], [7, "d", 11], [5, 5, 5]])
  370. df.iloc(axis=0)[2] = 5
  371. tm.assert_frame_equal(df, expected)
  372. df = DataFrame([[6, "c", 10], [7, "d", 11], [8, "e", 12]])
  373. expected = DataFrame([[6, "c", 5], [7, "d", 5], [8, "e", 5]])
  374. df.iloc(axis=1)[2] = 5
  375. tm.assert_frame_equal(df, expected)
  376. def test_iloc_setitem_list(self):
  377. # setitem with an iloc list
  378. df = DataFrame(
  379. np.arange(9).reshape((3, 3)), index=["A", "B", "C"], columns=["A", "B", "C"]
  380. )
  381. df.iloc[[0, 1], [1, 2]]
  382. df.iloc[[0, 1], [1, 2]] += 100
  383. expected = DataFrame(
  384. np.array([0, 101, 102, 3, 104, 105, 6, 7, 8]).reshape((3, 3)),
  385. index=["A", "B", "C"],
  386. columns=["A", "B", "C"],
  387. )
  388. tm.assert_frame_equal(df, expected)
  389. def test_iloc_setitem_pandas_object(self):
  390. # GH 17193
  391. s_orig = Series([0, 1, 2, 3])
  392. expected = Series([0, -1, -2, 3])
  393. s = s_orig.copy()
  394. s.iloc[Series([1, 2])] = [-1, -2]
  395. tm.assert_series_equal(s, expected)
  396. s = s_orig.copy()
  397. s.iloc[Index([1, 2])] = [-1, -2]
  398. tm.assert_series_equal(s, expected)
  399. def test_iloc_setitem_dups(self):
  400. # GH 6766
  401. # iloc with a mask aligning from another iloc
  402. df1 = DataFrame([{"A": None, "B": 1}, {"A": 2, "B": 2}])
  403. df2 = DataFrame([{"A": 3, "B": 3}, {"A": 4, "B": 4}])
  404. df = concat([df1, df2], axis=1)
  405. expected = df.fillna(3)
  406. inds = np.isnan(df.iloc[:, 0])
  407. mask = inds[inds].index
  408. df.iloc[mask, 0] = df.iloc[mask, 2]
  409. tm.assert_frame_equal(df, expected)
  410. # del a dup column across blocks
  411. expected = DataFrame({0: [1, 2], 1: [3, 4]})
  412. expected.columns = ["B", "B"]
  413. del df["A"]
  414. tm.assert_frame_equal(df, expected)
  415. # assign back to self
  416. df.iloc[[0, 1], [0, 1]] = df.iloc[[0, 1], [0, 1]]
  417. tm.assert_frame_equal(df, expected)
  418. # reversed x 2
  419. df.iloc[[1, 0], [0, 1]] = df.iloc[[1, 0], [0, 1]].reset_index(drop=True)
  420. df.iloc[[1, 0], [0, 1]] = df.iloc[[1, 0], [0, 1]].reset_index(drop=True)
  421. tm.assert_frame_equal(df, expected)
  422. def test_iloc_setitem_frame_duplicate_columns_multiple_blocks(
  423. self, using_array_manager
  424. ):
  425. # Same as the "assign back to self" check in test_iloc_setitem_dups
  426. # but on a DataFrame with multiple blocks
  427. df = DataFrame([[0, 1], [2, 3]], columns=["B", "B"])
  428. # setting float values that can be held by existing integer arrays
  429. # is inplace
  430. df.iloc[:, 0] = df.iloc[:, 0].astype("f8")
  431. if not using_array_manager:
  432. assert len(df._mgr.blocks) == 1
  433. # if the assigned values cannot be held by existing integer arrays,
  434. # we cast
  435. df.iloc[:, 0] = df.iloc[:, 0] + 0.5
  436. if not using_array_manager:
  437. assert len(df._mgr.blocks) == 2
  438. expected = df.copy()
  439. # assign back to self
  440. df.iloc[[0, 1], [0, 1]] = df.iloc[[0, 1], [0, 1]]
  441. tm.assert_frame_equal(df, expected)
  442. # TODO: GH#27620 this test used to compare iloc against ix; check if this
  443. # is redundant with another test comparing iloc against loc
  444. def test_iloc_getitem_frame(self):
  445. df = DataFrame(
  446. np.random.randn(10, 4), index=range(0, 20, 2), columns=range(0, 8, 2)
  447. )
  448. result = df.iloc[2]
  449. exp = df.loc[4]
  450. tm.assert_series_equal(result, exp)
  451. result = df.iloc[2, 2]
  452. exp = df.loc[4, 4]
  453. assert result == exp
  454. # slice
  455. result = df.iloc[4:8]
  456. expected = df.loc[8:14]
  457. tm.assert_frame_equal(result, expected)
  458. result = df.iloc[:, 2:3]
  459. expected = df.loc[:, 4:5]
  460. tm.assert_frame_equal(result, expected)
  461. # list of integers
  462. result = df.iloc[[0, 1, 3]]
  463. expected = df.loc[[0, 2, 6]]
  464. tm.assert_frame_equal(result, expected)
  465. result = df.iloc[[0, 1, 3], [0, 1]]
  466. expected = df.loc[[0, 2, 6], [0, 2]]
  467. tm.assert_frame_equal(result, expected)
  468. # neg indices
  469. result = df.iloc[[-1, 1, 3], [-1, 1]]
  470. expected = df.loc[[18, 2, 6], [6, 2]]
  471. tm.assert_frame_equal(result, expected)
  472. # dups indices
  473. result = df.iloc[[-1, -1, 1, 3], [-1, 1]]
  474. expected = df.loc[[18, 18, 2, 6], [6, 2]]
  475. tm.assert_frame_equal(result, expected)
  476. # with index-like
  477. s = Series(index=range(1, 5), dtype=object)
  478. result = df.iloc[s.index]
  479. expected = df.loc[[2, 4, 6, 8]]
  480. tm.assert_frame_equal(result, expected)
  481. def test_iloc_getitem_labelled_frame(self):
  482. # try with labelled frame
  483. df = DataFrame(
  484. np.random.randn(10, 4), index=list("abcdefghij"), columns=list("ABCD")
  485. )
  486. result = df.iloc[1, 1]
  487. exp = df.loc["b", "B"]
  488. assert result == exp
  489. result = df.iloc[:, 2:3]
  490. expected = df.loc[:, ["C"]]
  491. tm.assert_frame_equal(result, expected)
  492. # negative indexing
  493. result = df.iloc[-1, -1]
  494. exp = df.loc["j", "D"]
  495. assert result == exp
  496. # out-of-bounds exception
  497. msg = "index 5 is out of bounds for axis 0 with size 4"
  498. with pytest.raises(IndexError, match=msg):
  499. df.iloc[10, 5]
  500. # trying to use a label
  501. msg = (
  502. r"Location based indexing can only have \[integer, integer "
  503. r"slice \(START point is INCLUDED, END point is EXCLUDED\), "
  504. r"listlike of integers, boolean array\] types"
  505. )
  506. with pytest.raises(ValueError, match=msg):
  507. df.iloc["j", "D"]
  508. def test_iloc_getitem_doc_issue(self, using_array_manager):
  509. # multi axis slicing issue with single block
  510. # surfaced in GH 6059
  511. arr = np.random.randn(6, 4)
  512. index = date_range("20130101", periods=6)
  513. columns = list("ABCD")
  514. df = DataFrame(arr, index=index, columns=columns)
  515. # defines ref_locs
  516. df.describe()
  517. result = df.iloc[3:5, 0:2]
  518. str(result)
  519. result.dtypes
  520. expected = DataFrame(arr[3:5, 0:2], index=index[3:5], columns=columns[0:2])
  521. tm.assert_frame_equal(result, expected)
  522. # for dups
  523. df.columns = list("aaaa")
  524. result = df.iloc[3:5, 0:2]
  525. str(result)
  526. result.dtypes
  527. expected = DataFrame(arr[3:5, 0:2], index=index[3:5], columns=list("aa"))
  528. tm.assert_frame_equal(result, expected)
  529. # related
  530. arr = np.random.randn(6, 4)
  531. index = list(range(0, 12, 2))
  532. columns = list(range(0, 8, 2))
  533. df = DataFrame(arr, index=index, columns=columns)
  534. if not using_array_manager:
  535. df._mgr.blocks[0].mgr_locs
  536. result = df.iloc[1:5, 2:4]
  537. str(result)
  538. result.dtypes
  539. expected = DataFrame(arr[1:5, 2:4], index=index[1:5], columns=columns[2:4])
  540. tm.assert_frame_equal(result, expected)
  541. def test_iloc_setitem_series(self):
  542. df = DataFrame(
  543. np.random.randn(10, 4), index=list("abcdefghij"), columns=list("ABCD")
  544. )
  545. df.iloc[1, 1] = 1
  546. result = df.iloc[1, 1]
  547. assert result == 1
  548. df.iloc[:, 2:3] = 0
  549. expected = df.iloc[:, 2:3]
  550. result = df.iloc[:, 2:3]
  551. tm.assert_frame_equal(result, expected)
  552. s = Series(np.random.randn(10), index=range(0, 20, 2))
  553. s.iloc[1] = 1
  554. result = s.iloc[1]
  555. assert result == 1
  556. s.iloc[:4] = 0
  557. expected = s.iloc[:4]
  558. result = s.iloc[:4]
  559. tm.assert_series_equal(result, expected)
  560. s = Series([-1] * 6)
  561. s.iloc[0::2] = [0, 2, 4]
  562. s.iloc[1::2] = [1, 3, 5]
  563. result = s
  564. expected = Series([0, 1, 2, 3, 4, 5])
  565. tm.assert_series_equal(result, expected)
  566. def test_iloc_setitem_list_of_lists(self):
  567. # GH 7551
  568. # list-of-list is set incorrectly in mixed vs. single dtyped frames
  569. df = DataFrame(
  570. {"A": np.arange(5, dtype="int64"), "B": np.arange(5, 10, dtype="int64")}
  571. )
  572. df.iloc[2:4] = [[10, 11], [12, 13]]
  573. expected = DataFrame({"A": [0, 1, 10, 12, 4], "B": [5, 6, 11, 13, 9]})
  574. tm.assert_frame_equal(df, expected)
  575. df = DataFrame(
  576. {"A": ["a", "b", "c", "d", "e"], "B": np.arange(5, 10, dtype="int64")}
  577. )
  578. df.iloc[2:4] = [["x", 11], ["y", 13]]
  579. expected = DataFrame({"A": ["a", "b", "x", "y", "e"], "B": [5, 6, 11, 13, 9]})
  580. tm.assert_frame_equal(df, expected)
  581. @pytest.mark.parametrize("indexer", [[0], slice(None, 1, None), np.array([0])])
  582. @pytest.mark.parametrize("value", [["Z"], np.array(["Z"])])
  583. def test_iloc_setitem_with_scalar_index(self, indexer, value):
  584. # GH #19474
  585. # assigning like "df.iloc[0, [0]] = ['Z']" should be evaluated
  586. # elementwisely, not using "setter('A', ['Z'])".
  587. df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"])
  588. df.iloc[0, indexer] = value
  589. result = df.iloc[0, 0]
  590. assert is_scalar(result) and result == "Z"
  591. def test_iloc_mask(self):
  592. # GH 3631, iloc with a mask (of a series) should raise
  593. df = DataFrame(list(range(5)), index=list("ABCDE"), columns=["a"])
  594. mask = df.a % 2 == 0
  595. msg = "iLocation based boolean indexing cannot use an indexable as a mask"
  596. with pytest.raises(ValueError, match=msg):
  597. df.iloc[mask]
  598. mask.index = range(len(mask))
  599. msg = "iLocation based boolean indexing on an integer type is not available"
  600. with pytest.raises(NotImplementedError, match=msg):
  601. df.iloc[mask]
  602. # ndarray ok
  603. result = df.iloc[np.array([True] * len(mask), dtype=bool)]
  604. tm.assert_frame_equal(result, df)
  605. # the possibilities
  606. locs = np.arange(4)
  607. nums = 2**locs
  608. reps = [bin(num) for num in nums]
  609. df = DataFrame({"locs": locs, "nums": nums}, reps)
  610. expected = {
  611. (None, ""): "0b1100",
  612. (None, ".loc"): "0b1100",
  613. (None, ".iloc"): "0b1100",
  614. ("index", ""): "0b11",
  615. ("index", ".loc"): "0b11",
  616. ("index", ".iloc"): (
  617. "iLocation based boolean indexing cannot use an indexable as a mask"
  618. ),
  619. ("locs", ""): "Unalignable boolean Series provided as indexer "
  620. "(index of the boolean Series and of the indexed "
  621. "object do not match).",
  622. ("locs", ".loc"): "Unalignable boolean Series provided as indexer "
  623. "(index of the boolean Series and of the "
  624. "indexed object do not match).",
  625. ("locs", ".iloc"): (
  626. "iLocation based boolean indexing on an "
  627. "integer type is not available"
  628. ),
  629. }
  630. # UserWarnings from reindex of a boolean mask
  631. with catch_warnings(record=True):
  632. simplefilter("ignore", UserWarning)
  633. for idx in [None, "index", "locs"]:
  634. mask = (df.nums > 2).values
  635. if idx:
  636. mask = Series(mask, list(reversed(getattr(df, idx))))
  637. for method in ["", ".loc", ".iloc"]:
  638. try:
  639. if method:
  640. accessor = getattr(df, method[1:])
  641. else:
  642. accessor = df
  643. answer = str(bin(accessor[mask]["nums"].sum()))
  644. except (ValueError, IndexingError, NotImplementedError) as e:
  645. answer = str(e)
  646. key = (
  647. idx,
  648. method,
  649. )
  650. r = expected.get(key)
  651. if r != answer:
  652. raise AssertionError(
  653. f"[{key}] does not match [{answer}], received [{r}]"
  654. )
  655. def test_iloc_non_unique_indexing(self):
  656. # GH 4017, non-unique indexing (on the axis)
  657. df = DataFrame({"A": [0.1] * 3000, "B": [1] * 3000})
  658. idx = np.arange(30) * 99
  659. expected = df.iloc[idx]
  660. df3 = concat([df, 2 * df, 3 * df])
  661. result = df3.iloc[idx]
  662. tm.assert_frame_equal(result, expected)
  663. df2 = DataFrame({"A": [0.1] * 1000, "B": [1] * 1000})
  664. df2 = concat([df2, 2 * df2, 3 * df2])
  665. with pytest.raises(KeyError, match="not in index"):
  666. df2.loc[idx]
  667. def test_iloc_empty_list_indexer_is_ok(self):
  668. df = tm.makeCustomDataframe(5, 2)
  669. # vertical empty
  670. tm.assert_frame_equal(
  671. df.iloc[:, []],
  672. df.iloc[:, :0],
  673. check_index_type=True,
  674. check_column_type=True,
  675. )
  676. # horizontal empty
  677. tm.assert_frame_equal(
  678. df.iloc[[], :],
  679. df.iloc[:0, :],
  680. check_index_type=True,
  681. check_column_type=True,
  682. )
  683. # horizontal empty
  684. tm.assert_frame_equal(
  685. df.iloc[[]], df.iloc[:0, :], check_index_type=True, check_column_type=True
  686. )
  687. def test_identity_slice_returns_new_object(self, using_copy_on_write):
  688. # GH13873
  689. original_df = DataFrame({"a": [1, 2, 3]})
  690. sliced_df = original_df.iloc[:]
  691. assert sliced_df is not original_df
  692. # should be a shallow copy
  693. assert np.shares_memory(original_df["a"], sliced_df["a"])
  694. # Setting using .loc[:, "a"] sets inplace so alters both sliced and orig
  695. # depending on CoW
  696. original_df.loc[:, "a"] = [4, 4, 4]
  697. if using_copy_on_write:
  698. assert (sliced_df["a"] == [1, 2, 3]).all()
  699. else:
  700. assert (sliced_df["a"] == 4).all()
  701. original_series = Series([1, 2, 3, 4, 5, 6])
  702. sliced_series = original_series.iloc[:]
  703. assert sliced_series is not original_series
  704. # should also be a shallow copy
  705. original_series[:3] = [7, 8, 9]
  706. if using_copy_on_write:
  707. # shallow copy not updated (CoW)
  708. assert all(sliced_series[:3] == [1, 2, 3])
  709. else:
  710. assert all(sliced_series[:3] == [7, 8, 9])
  711. def test_indexing_zerodim_np_array(self):
  712. # GH24919
  713. df = DataFrame([[1, 2], [3, 4]])
  714. result = df.iloc[np.array(0)]
  715. s = Series([1, 2], name=0)
  716. tm.assert_series_equal(result, s)
  717. def test_series_indexing_zerodim_np_array(self):
  718. # GH24919
  719. s = Series([1, 2])
  720. result = s.iloc[np.array(0)]
  721. assert result == 1
  722. def test_iloc_setitem_categorical_updates_inplace(self):
  723. # Mixed dtype ensures we go through take_split_path in setitem_with_indexer
  724. cat = Categorical(["A", "B", "C"])
  725. df = DataFrame({1: cat, 2: [1, 2, 3]}, copy=False)
  726. assert tm.shares_memory(df[1], cat)
  727. # With the enforcement of GH#45333 in 2.0, this modifies original
  728. # values inplace
  729. df.iloc[:, 0] = cat[::-1]
  730. assert tm.shares_memory(df[1], cat)
  731. expected = Categorical(["C", "B", "A"], categories=["A", "B", "C"])
  732. tm.assert_categorical_equal(cat, expected)
  733. def test_iloc_with_boolean_operation(self):
  734. # GH 20627
  735. result = DataFrame([[0, 1], [2, 3], [4, 5], [6, np.nan]])
  736. result.iloc[result.index <= 2] *= 2
  737. expected = DataFrame([[0, 2], [4, 6], [8, 10], [6, np.nan]])
  738. tm.assert_frame_equal(result, expected)
  739. result.iloc[result.index > 2] *= 2
  740. expected = DataFrame([[0, 2], [4, 6], [8, 10], [12, np.nan]])
  741. tm.assert_frame_equal(result, expected)
  742. result.iloc[[True, True, False, False]] *= 2
  743. expected = DataFrame([[0, 4], [8, 12], [8, 10], [12, np.nan]])
  744. tm.assert_frame_equal(result, expected)
  745. result.iloc[[False, False, True, True]] /= 2
  746. expected = DataFrame([[0, 4.0], [8, 12.0], [4, 5.0], [6, np.nan]])
  747. tm.assert_frame_equal(result, expected)
  748. def test_iloc_getitem_singlerow_slice_categoricaldtype_gives_series(self):
  749. # GH#29521
  750. df = DataFrame({"x": Categorical("a b c d e".split())})
  751. result = df.iloc[0]
  752. raw_cat = Categorical(["a"], categories=["a", "b", "c", "d", "e"])
  753. expected = Series(raw_cat, index=["x"], name=0, dtype="category")
  754. tm.assert_series_equal(result, expected)
  755. def test_iloc_getitem_categorical_values(self):
  756. # GH#14580
  757. # test iloc() on Series with Categorical data
  758. ser = Series([1, 2, 3]).astype("category")
  759. # get slice
  760. result = ser.iloc[0:2]
  761. expected = Series([1, 2]).astype(CategoricalDtype([1, 2, 3]))
  762. tm.assert_series_equal(result, expected)
  763. # get list of indexes
  764. result = ser.iloc[[0, 1]]
  765. expected = Series([1, 2]).astype(CategoricalDtype([1, 2, 3]))
  766. tm.assert_series_equal(result, expected)
  767. # get boolean array
  768. result = ser.iloc[[True, False, False]]
  769. expected = Series([1]).astype(CategoricalDtype([1, 2, 3]))
  770. tm.assert_series_equal(result, expected)
  771. @pytest.mark.parametrize("value", [None, NaT, np.nan])
  772. def test_iloc_setitem_td64_values_cast_na(self, value):
  773. # GH#18586
  774. series = Series([0, 1, 2], dtype="timedelta64[ns]")
  775. series.iloc[0] = value
  776. expected = Series([NaT, 1, 2], dtype="timedelta64[ns]")
  777. tm.assert_series_equal(series, expected)
  778. @pytest.mark.parametrize("not_na", [Interval(0, 1), "a", 1.0])
  779. def test_setitem_mix_of_nan_and_interval(self, not_na, nulls_fixture):
  780. # GH#27937
  781. dtype = CategoricalDtype(categories=[not_na])
  782. ser = Series(
  783. [nulls_fixture, nulls_fixture, nulls_fixture, nulls_fixture], dtype=dtype
  784. )
  785. ser.iloc[:3] = [nulls_fixture, not_na, nulls_fixture]
  786. exp = Series([nulls_fixture, not_na, nulls_fixture, nulls_fixture], dtype=dtype)
  787. tm.assert_series_equal(ser, exp)
  788. def test_iloc_setitem_empty_frame_raises_with_3d_ndarray(self):
  789. idx = Index([])
  790. obj = DataFrame(np.random.randn(len(idx), len(idx)), index=idx, columns=idx)
  791. nd3 = np.random.randint(5, size=(2, 2, 2))
  792. msg = f"Cannot set values with ndim > {obj.ndim}"
  793. with pytest.raises(ValueError, match=msg):
  794. obj.iloc[nd3] = 0
  795. @pytest.mark.parametrize("indexer", [tm.loc, tm.iloc])
  796. def test_iloc_getitem_read_only_values(self, indexer):
  797. # GH#10043 this is fundamentally a test for iloc, but test loc while
  798. # we're here
  799. rw_array = np.eye(10)
  800. rw_df = DataFrame(rw_array)
  801. ro_array = np.eye(10)
  802. ro_array.setflags(write=False)
  803. ro_df = DataFrame(ro_array)
  804. tm.assert_frame_equal(indexer(rw_df)[[1, 2, 3]], indexer(ro_df)[[1, 2, 3]])
  805. tm.assert_frame_equal(indexer(rw_df)[[1]], indexer(ro_df)[[1]])
  806. tm.assert_series_equal(indexer(rw_df)[1], indexer(ro_df)[1])
  807. tm.assert_frame_equal(indexer(rw_df)[1:3], indexer(ro_df)[1:3])
  808. def test_iloc_getitem_readonly_key(self):
  809. # GH#17192 iloc with read-only array raising TypeError
  810. df = DataFrame({"data": np.ones(100, dtype="float64")})
  811. indices = np.array([1, 3, 6])
  812. indices.flags.writeable = False
  813. result = df.iloc[indices]
  814. expected = df.loc[[1, 3, 6]]
  815. tm.assert_frame_equal(result, expected)
  816. result = df["data"].iloc[indices]
  817. expected = df["data"].loc[[1, 3, 6]]
  818. tm.assert_series_equal(result, expected)
  819. def test_iloc_assign_series_to_df_cell(self):
  820. # GH 37593
  821. df = DataFrame(columns=["a"], index=[0])
  822. df.iloc[0, 0] = Series([1, 2, 3])
  823. expected = DataFrame({"a": [Series([1, 2, 3])]}, columns=["a"], index=[0])
  824. tm.assert_frame_equal(df, expected)
  825. @pytest.mark.parametrize("klass", [list, np.array])
  826. def test_iloc_setitem_bool_indexer(self, klass):
  827. # GH#36741
  828. df = DataFrame({"flag": ["x", "y", "z"], "value": [1, 3, 4]})
  829. indexer = klass([True, False, False])
  830. df.iloc[indexer, 1] = df.iloc[indexer, 1] * 2
  831. expected = DataFrame({"flag": ["x", "y", "z"], "value": [2, 3, 4]})
  832. tm.assert_frame_equal(df, expected)
  833. @pytest.mark.parametrize("indexer", [[1], slice(1, 2)])
  834. def test_iloc_setitem_pure_position_based(self, indexer):
  835. # GH#22046
  836. df1 = DataFrame({"a2": [11, 12, 13], "b2": [14, 15, 16]})
  837. df2 = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]})
  838. df2.iloc[:, indexer] = df1.iloc[:, [0]]
  839. expected = DataFrame({"a": [1, 2, 3], "b": [11, 12, 13], "c": [7, 8, 9]})
  840. tm.assert_frame_equal(df2, expected)
  841. def test_iloc_setitem_dictionary_value(self):
  842. # GH#37728
  843. df = DataFrame({"x": [1, 2], "y": [2, 2]})
  844. rhs = {"x": 9, "y": 99}
  845. df.iloc[1] = rhs
  846. expected = DataFrame({"x": [1, 9], "y": [2, 99]})
  847. tm.assert_frame_equal(df, expected)
  848. # GH#38335 same thing, mixed dtypes
  849. df = DataFrame({"x": [1, 2], "y": [2.0, 2.0]})
  850. df.iloc[1] = rhs
  851. expected = DataFrame({"x": [1, 9], "y": [2.0, 99.0]})
  852. tm.assert_frame_equal(df, expected)
  853. def test_iloc_getitem_float_duplicates(self):
  854. df = DataFrame(
  855. np.random.randn(3, 3), index=[0.1, 0.2, 0.2], columns=list("abc")
  856. )
  857. expect = df.iloc[1:]
  858. tm.assert_frame_equal(df.loc[0.2], expect)
  859. expect = df.iloc[1:, 0]
  860. tm.assert_series_equal(df.loc[0.2, "a"], expect)
  861. df.index = [1, 0.2, 0.2]
  862. expect = df.iloc[1:]
  863. tm.assert_frame_equal(df.loc[0.2], expect)
  864. expect = df.iloc[1:, 0]
  865. tm.assert_series_equal(df.loc[0.2, "a"], expect)
  866. df = DataFrame(
  867. np.random.randn(4, 3), index=[1, 0.2, 0.2, 1], columns=list("abc")
  868. )
  869. expect = df.iloc[1:-1]
  870. tm.assert_frame_equal(df.loc[0.2], expect)
  871. expect = df.iloc[1:-1, 0]
  872. tm.assert_series_equal(df.loc[0.2, "a"], expect)
  873. df.index = [0.1, 0.2, 2, 0.2]
  874. expect = df.iloc[[1, -1]]
  875. tm.assert_frame_equal(df.loc[0.2], expect)
  876. expect = df.iloc[[1, -1], 0]
  877. tm.assert_series_equal(df.loc[0.2, "a"], expect)
  878. def test_iloc_setitem_custom_object(self):
  879. # iloc with an object
  880. class TO:
  881. def __init__(self, value) -> None:
  882. self.value = value
  883. def __str__(self) -> str:
  884. return f"[{self.value}]"
  885. __repr__ = __str__
  886. def __eq__(self, other) -> bool:
  887. return self.value == other.value
  888. def view(self):
  889. return self
  890. df = DataFrame(index=[0, 1], columns=[0])
  891. df.iloc[1, 0] = TO(1)
  892. df.iloc[1, 0] = TO(2)
  893. result = DataFrame(index=[0, 1], columns=[0])
  894. result.iloc[1, 0] = TO(2)
  895. tm.assert_frame_equal(result, df)
  896. # remains object dtype even after setting it back
  897. df = DataFrame(index=[0, 1], columns=[0])
  898. df.iloc[1, 0] = TO(1)
  899. df.iloc[1, 0] = np.nan
  900. result = DataFrame(index=[0, 1], columns=[0])
  901. tm.assert_frame_equal(result, df)
  902. def test_iloc_getitem_with_duplicates(self):
  903. df = DataFrame(np.random.rand(3, 3), columns=list("ABC"), index=list("aab"))
  904. result = df.iloc[0]
  905. assert isinstance(result, Series)
  906. tm.assert_almost_equal(result.values, df.values[0])
  907. result = df.T.iloc[:, 0]
  908. assert isinstance(result, Series)
  909. tm.assert_almost_equal(result.values, df.values[0])
  910. def test_iloc_getitem_with_duplicates2(self):
  911. # GH#2259
  912. df = DataFrame([[1, 2, 3], [4, 5, 6]], columns=[1, 1, 2])
  913. result = df.iloc[:, [0]]
  914. expected = df.take([0], axis=1)
  915. tm.assert_frame_equal(result, expected)
  916. def test_iloc_interval(self):
  917. # GH#17130
  918. df = DataFrame({Interval(1, 2): [1, 2]})
  919. result = df.iloc[0]
  920. expected = Series({Interval(1, 2): 1}, name=0)
  921. tm.assert_series_equal(result, expected)
  922. result = df.iloc[:, 0]
  923. expected = Series([1, 2], name=Interval(1, 2))
  924. tm.assert_series_equal(result, expected)
  925. result = df.copy()
  926. result.iloc[:, 0] += 1
  927. expected = DataFrame({Interval(1, 2): [2, 3]})
  928. tm.assert_frame_equal(result, expected)
  929. @pytest.mark.parametrize("indexing_func", [list, np.array])
  930. @pytest.mark.parametrize("rhs_func", [list, np.array])
  931. def test_loc_setitem_boolean_list(self, rhs_func, indexing_func):
  932. # GH#20438 testing specifically list key, not arraylike
  933. ser = Series([0, 1, 2])
  934. ser.iloc[indexing_func([True, False, True])] = rhs_func([5, 10])
  935. expected = Series([5, 1, 10])
  936. tm.assert_series_equal(ser, expected)
  937. df = DataFrame({"a": [0, 1, 2]})
  938. df.iloc[indexing_func([True, False, True])] = rhs_func([[5], [10]])
  939. expected = DataFrame({"a": [5, 1, 10]})
  940. tm.assert_frame_equal(df, expected)
  941. def test_iloc_getitem_slice_negative_step_ea_block(self):
  942. # GH#44551
  943. df = DataFrame({"A": [1, 2, 3]}, dtype="Int64")
  944. res = df.iloc[:, ::-1]
  945. tm.assert_frame_equal(res, df)
  946. df["B"] = "foo"
  947. res = df.iloc[:, ::-1]
  948. expected = DataFrame({"B": df["B"], "A": df["A"]})
  949. tm.assert_frame_equal(res, expected)
  950. def test_iloc_setitem_2d_ndarray_into_ea_block(self):
  951. # GH#44703
  952. df = DataFrame({"status": ["a", "b", "c"]}, dtype="category")
  953. df.iloc[np.array([0, 1]), np.array([0])] = np.array([["a"], ["a"]])
  954. expected = DataFrame({"status": ["a", "a", "c"]}, dtype=df["status"].dtype)
  955. tm.assert_frame_equal(df, expected)
  956. @td.skip_array_manager_not_yet_implemented
  957. def test_iloc_getitem_int_single_ea_block_view(self):
  958. # GH#45241
  959. # TODO: make an extension interface test for this?
  960. arr = interval_range(1, 10.0)._values
  961. df = DataFrame(arr)
  962. # ser should be a *view* on the DataFrame data
  963. ser = df.iloc[2]
  964. # if we have a view, then changing arr[2] should also change ser[0]
  965. assert arr[2] != arr[-1] # otherwise the rest isn't meaningful
  966. arr[2] = arr[-1]
  967. assert ser[0] == arr[-1]
  968. def test_iloc_setitem_multicolumn_to_datetime(self):
  969. # GH#20511
  970. df = DataFrame({"A": ["2022-01-01", "2022-01-02"], "B": ["2021", "2022"]})
  971. df.iloc[:, [0]] = DataFrame({"A": to_datetime(["2021", "2022"])})
  972. expected = DataFrame(
  973. {
  974. "A": [
  975. Timestamp("2021-01-01 00:00:00"),
  976. Timestamp("2022-01-01 00:00:00"),
  977. ],
  978. "B": ["2021", "2022"],
  979. }
  980. )
  981. tm.assert_frame_equal(df, expected, check_dtype=False)
  982. class TestILocErrors:
  983. # NB: this test should work for _any_ Series we can pass as
  984. # series_with_simple_index
  985. def test_iloc_float_raises(self, series_with_simple_index, frame_or_series):
  986. # GH#4892
  987. # float_indexers should raise exceptions
  988. # on appropriate Index types & accessors
  989. # this duplicates the code below
  990. # but is specifically testing for the error
  991. # message
  992. obj = series_with_simple_index
  993. if frame_or_series is DataFrame:
  994. obj = obj.to_frame()
  995. msg = "Cannot index by location index with a non-integer key"
  996. with pytest.raises(TypeError, match=msg):
  997. obj.iloc[3.0]
  998. with pytest.raises(IndexError, match=_slice_iloc_msg):
  999. obj.iloc[3.0] = 0
  1000. def test_iloc_getitem_setitem_fancy_exceptions(self, float_frame):
  1001. with pytest.raises(IndexingError, match="Too many indexers"):
  1002. float_frame.iloc[:, :, :]
  1003. with pytest.raises(IndexError, match="too many indices for array"):
  1004. # GH#32257 we let numpy do validation, get their exception
  1005. float_frame.iloc[:, :, :] = 1
  1006. def test_iloc_frame_indexer(self):
  1007. # GH#39004
  1008. df = DataFrame({"a": [1, 2, 3]})
  1009. indexer = DataFrame({"a": [True, False, True]})
  1010. msg = "DataFrame indexer for .iloc is not supported. Consider using .loc"
  1011. with pytest.raises(TypeError, match=msg):
  1012. df.iloc[indexer] = 1
  1013. msg = (
  1014. "DataFrame indexer is not allowed for .iloc\n"
  1015. "Consider using .loc for automatic alignment."
  1016. )
  1017. with pytest.raises(IndexError, match=msg):
  1018. df.iloc[indexer]
  1019. class TestILocSetItemDuplicateColumns:
  1020. def test_iloc_setitem_scalar_duplicate_columns(self):
  1021. # GH#15686, duplicate columns and mixed dtype
  1022. df1 = DataFrame([{"A": None, "B": 1}, {"A": 2, "B": 2}])
  1023. df2 = DataFrame([{"A": 3, "B": 3}, {"A": 4, "B": 4}])
  1024. df = concat([df1, df2], axis=1)
  1025. df.iloc[0, 0] = -1
  1026. assert df.iloc[0, 0] == -1
  1027. assert df.iloc[0, 2] == 3
  1028. assert df.dtypes.iloc[2] == np.int64
  1029. def test_iloc_setitem_list_duplicate_columns(self):
  1030. # GH#22036 setting with same-sized list
  1031. df = DataFrame([[0, "str", "str2"]], columns=["a", "b", "b"])
  1032. df.iloc[:, 2] = ["str3"]
  1033. expected = DataFrame([[0, "str", "str3"]], columns=["a", "b", "b"])
  1034. tm.assert_frame_equal(df, expected)
  1035. def test_iloc_setitem_series_duplicate_columns(self):
  1036. df = DataFrame(
  1037. np.arange(8, dtype=np.int64).reshape(2, 4), columns=["A", "B", "A", "B"]
  1038. )
  1039. df.iloc[:, 0] = df.iloc[:, 0].astype(np.float64)
  1040. assert df.dtypes.iloc[2] == np.int64
  1041. @pytest.mark.parametrize(
  1042. ["dtypes", "init_value", "expected_value"],
  1043. [("int64", "0", 0), ("float", "1.2", 1.2)],
  1044. )
  1045. def test_iloc_setitem_dtypes_duplicate_columns(
  1046. self, dtypes, init_value, expected_value
  1047. ):
  1048. # GH#22035
  1049. df = DataFrame([[init_value, "str", "str2"]], columns=["a", "b", "b"])
  1050. # with the enforcement of GH#45333 in 2.0, this sets values inplace,
  1051. # so we retain object dtype
  1052. df.iloc[:, 0] = df.iloc[:, 0].astype(dtypes)
  1053. expected_df = DataFrame(
  1054. [[expected_value, "str", "str2"]],
  1055. columns=["a", "b", "b"],
  1056. dtype=object,
  1057. )
  1058. tm.assert_frame_equal(df, expected_df)
  1059. class TestILocCallable:
  1060. def test_frame_iloc_getitem_callable(self):
  1061. # GH#11485
  1062. df = DataFrame({"X": [1, 2, 3, 4], "Y": list("aabb")}, index=list("ABCD"))
  1063. # return location
  1064. res = df.iloc[lambda x: [1, 3]]
  1065. tm.assert_frame_equal(res, df.iloc[[1, 3]])
  1066. res = df.iloc[lambda x: [1, 3], :]
  1067. tm.assert_frame_equal(res, df.iloc[[1, 3], :])
  1068. res = df.iloc[lambda x: [1, 3], lambda x: 0]
  1069. tm.assert_series_equal(res, df.iloc[[1, 3], 0])
  1070. res = df.iloc[lambda x: [1, 3], lambda x: [0]]
  1071. tm.assert_frame_equal(res, df.iloc[[1, 3], [0]])
  1072. # mixture
  1073. res = df.iloc[[1, 3], lambda x: 0]
  1074. tm.assert_series_equal(res, df.iloc[[1, 3], 0])
  1075. res = df.iloc[[1, 3], lambda x: [0]]
  1076. tm.assert_frame_equal(res, df.iloc[[1, 3], [0]])
  1077. res = df.iloc[lambda x: [1, 3], 0]
  1078. tm.assert_series_equal(res, df.iloc[[1, 3], 0])
  1079. res = df.iloc[lambda x: [1, 3], [0]]
  1080. tm.assert_frame_equal(res, df.iloc[[1, 3], [0]])
  1081. def test_frame_iloc_setitem_callable(self):
  1082. # GH#11485
  1083. df = DataFrame({"X": [1, 2, 3, 4], "Y": list("aabb")}, index=list("ABCD"))
  1084. # return location
  1085. res = df.copy()
  1086. res.iloc[lambda x: [1, 3]] = 0
  1087. exp = df.copy()
  1088. exp.iloc[[1, 3]] = 0
  1089. tm.assert_frame_equal(res, exp)
  1090. res = df.copy()
  1091. res.iloc[lambda x: [1, 3], :] = -1
  1092. exp = df.copy()
  1093. exp.iloc[[1, 3], :] = -1
  1094. tm.assert_frame_equal(res, exp)
  1095. res = df.copy()
  1096. res.iloc[lambda x: [1, 3], lambda x: 0] = 5
  1097. exp = df.copy()
  1098. exp.iloc[[1, 3], 0] = 5
  1099. tm.assert_frame_equal(res, exp)
  1100. res = df.copy()
  1101. res.iloc[lambda x: [1, 3], lambda x: [0]] = 25
  1102. exp = df.copy()
  1103. exp.iloc[[1, 3], [0]] = 25
  1104. tm.assert_frame_equal(res, exp)
  1105. # mixture
  1106. res = df.copy()
  1107. res.iloc[[1, 3], lambda x: 0] = -3
  1108. exp = df.copy()
  1109. exp.iloc[[1, 3], 0] = -3
  1110. tm.assert_frame_equal(res, exp)
  1111. res = df.copy()
  1112. res.iloc[[1, 3], lambda x: [0]] = -5
  1113. exp = df.copy()
  1114. exp.iloc[[1, 3], [0]] = -5
  1115. tm.assert_frame_equal(res, exp)
  1116. res = df.copy()
  1117. res.iloc[lambda x: [1, 3], 0] = 10
  1118. exp = df.copy()
  1119. exp.iloc[[1, 3], 0] = 10
  1120. tm.assert_frame_equal(res, exp)
  1121. res = df.copy()
  1122. res.iloc[lambda x: [1, 3], [0]] = [-5, -5]
  1123. exp = df.copy()
  1124. exp.iloc[[1, 3], [0]] = [-5, -5]
  1125. tm.assert_frame_equal(res, exp)
  1126. class TestILocSeries:
  1127. def test_iloc(self, using_copy_on_write):
  1128. ser = Series(np.random.randn(10), index=list(range(0, 20, 2)))
  1129. ser_original = ser.copy()
  1130. for i in range(len(ser)):
  1131. result = ser.iloc[i]
  1132. exp = ser[ser.index[i]]
  1133. tm.assert_almost_equal(result, exp)
  1134. # pass a slice
  1135. result = ser.iloc[slice(1, 3)]
  1136. expected = ser.loc[2:4]
  1137. tm.assert_series_equal(result, expected)
  1138. # test slice is a view
  1139. with tm.assert_produces_warning(None):
  1140. # GH#45324 make sure we aren't giving a spurious FutureWarning
  1141. result[:] = 0
  1142. if using_copy_on_write:
  1143. tm.assert_series_equal(ser, ser_original)
  1144. else:
  1145. assert (ser.iloc[1:3] == 0).all()
  1146. # list of integers
  1147. result = ser.iloc[[0, 2, 3, 4, 5]]
  1148. expected = ser.reindex(ser.index[[0, 2, 3, 4, 5]])
  1149. tm.assert_series_equal(result, expected)
  1150. def test_iloc_getitem_nonunique(self):
  1151. ser = Series([0, 1, 2], index=[0, 1, 0])
  1152. assert ser.iloc[2] == 2
  1153. def test_iloc_setitem_pure_position_based(self):
  1154. # GH#22046
  1155. ser1 = Series([1, 2, 3])
  1156. ser2 = Series([4, 5, 6], index=[1, 0, 2])
  1157. ser1.iloc[1:3] = ser2.iloc[1:3]
  1158. expected = Series([1, 5, 6])
  1159. tm.assert_series_equal(ser1, expected)
  1160. def test_iloc_nullable_int64_size_1_nan(self):
  1161. # GH 31861
  1162. result = DataFrame({"a": ["test"], "b": [np.nan]})
  1163. result.loc[:, "b"] = result.loc[:, "b"].astype("Int64")
  1164. expected = DataFrame({"a": ["test"], "b": array([NA], dtype="Int64")})
  1165. tm.assert_frame_equal(result, expected)