test_scalar.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. """ test scalar indexing, including at and iat """
  2. from datetime import (
  3. datetime,
  4. timedelta,
  5. )
  6. import itertools
  7. import numpy as np
  8. import pytest
  9. from pandas import (
  10. DataFrame,
  11. Series,
  12. Timedelta,
  13. Timestamp,
  14. date_range,
  15. )
  16. import pandas._testing as tm
  17. def generate_indices(f, values=False):
  18. """
  19. generate the indices
  20. if values is True , use the axis values
  21. is False, use the range
  22. """
  23. axes = f.axes
  24. if values:
  25. axes = (list(range(len(ax))) for ax in axes)
  26. return itertools.product(*axes)
  27. class TestScalar:
  28. @pytest.mark.parametrize("kind", ["series", "frame"])
  29. @pytest.mark.parametrize("col", ["ints", "uints"])
  30. def test_iat_set_ints(self, kind, col, request):
  31. f = request.getfixturevalue(f"{kind}_{col}")
  32. indices = generate_indices(f, True)
  33. for i in indices:
  34. f.iat[i] = 1
  35. expected = f.values[i]
  36. tm.assert_almost_equal(expected, 1)
  37. @pytest.mark.parametrize("kind", ["series", "frame"])
  38. @pytest.mark.parametrize("col", ["labels", "ts", "floats"])
  39. def test_iat_set_other(self, kind, col, request):
  40. f = request.getfixturevalue(f"{kind}_{col}")
  41. msg = "iAt based indexing can only have integer indexers"
  42. with pytest.raises(ValueError, match=msg):
  43. idx = next(generate_indices(f, False))
  44. f.iat[idx] = 1
  45. @pytest.mark.parametrize("kind", ["series", "frame"])
  46. @pytest.mark.parametrize("col", ["ints", "uints", "labels", "ts", "floats"])
  47. def test_at_set_ints_other(self, kind, col, request):
  48. f = request.getfixturevalue(f"{kind}_{col}")
  49. indices = generate_indices(f, False)
  50. for i in indices:
  51. f.at[i] = 1
  52. expected = f.loc[i]
  53. tm.assert_almost_equal(expected, 1)
  54. class TestAtAndiAT:
  55. # at and iat tests that don't need Base class
  56. def test_float_index_at_iat(self):
  57. ser = Series([1, 2, 3], index=[0.1, 0.2, 0.3])
  58. for el, item in ser.items():
  59. assert ser.at[el] == item
  60. for i in range(len(ser)):
  61. assert ser.iat[i] == i + 1
  62. def test_at_iat_coercion(self):
  63. # as timestamp is not a tuple!
  64. dates = date_range("1/1/2000", periods=8)
  65. df = DataFrame(
  66. np.random.default_rng(2).standard_normal((8, 4)),
  67. index=dates,
  68. columns=["A", "B", "C", "D"],
  69. )
  70. s = df["A"]
  71. result = s.at[dates[5]]
  72. xp = s.values[5]
  73. assert result == xp
  74. @pytest.mark.parametrize(
  75. "ser, expected",
  76. [
  77. [
  78. Series(["2014-01-01", "2014-02-02"], dtype="datetime64[ns]"),
  79. Timestamp("2014-02-02"),
  80. ],
  81. [
  82. Series(["1 days", "2 days"], dtype="timedelta64[ns]"),
  83. Timedelta("2 days"),
  84. ],
  85. ],
  86. )
  87. def test_iloc_iat_coercion_datelike(self, indexer_ial, ser, expected):
  88. # GH 7729
  89. # make sure we are boxing the returns
  90. result = indexer_ial(ser)[1]
  91. assert result == expected
  92. def test_imethods_with_dups(self):
  93. # GH6493
  94. # iat/iloc with dups
  95. s = Series(range(5), index=[1, 1, 2, 2, 3], dtype="int64")
  96. result = s.iloc[2]
  97. assert result == 2
  98. result = s.iat[2]
  99. assert result == 2
  100. msg = "index 10 is out of bounds for axis 0 with size 5"
  101. with pytest.raises(IndexError, match=msg):
  102. s.iat[10]
  103. msg = "index -10 is out of bounds for axis 0 with size 5"
  104. with pytest.raises(IndexError, match=msg):
  105. s.iat[-10]
  106. result = s.iloc[[2, 3]]
  107. expected = Series([2, 3], [2, 2], dtype="int64")
  108. tm.assert_series_equal(result, expected)
  109. df = s.to_frame()
  110. result = df.iloc[2]
  111. expected = Series(2, index=[0], name=2)
  112. tm.assert_series_equal(result, expected)
  113. result = df.iat[2, 0]
  114. assert result == 2
  115. def test_frame_at_with_duplicate_axes(self):
  116. # GH#33041
  117. arr = np.random.default_rng(2).standard_normal(6).reshape(3, 2)
  118. df = DataFrame(arr, columns=["A", "A"])
  119. result = df.at[0, "A"]
  120. expected = df.iloc[0].copy()
  121. tm.assert_series_equal(result, expected)
  122. result = df.T.at["A", 0]
  123. tm.assert_series_equal(result, expected)
  124. # setter
  125. df.at[1, "A"] = 2
  126. expected = Series([2.0, 2.0], index=["A", "A"], name=1)
  127. tm.assert_series_equal(df.iloc[1], expected)
  128. def test_at_getitem_dt64tz_values(self):
  129. # gh-15822
  130. df = DataFrame(
  131. {
  132. "name": ["John", "Anderson"],
  133. "date": [
  134. Timestamp(2017, 3, 13, 13, 32, 56),
  135. Timestamp(2017, 2, 16, 12, 10, 3),
  136. ],
  137. }
  138. )
  139. df["date"] = df["date"].dt.tz_localize("Asia/Shanghai")
  140. expected = Timestamp("2017-03-13 13:32:56+0800", tz="Asia/Shanghai")
  141. result = df.loc[0, "date"]
  142. assert result == expected
  143. result = df.at[0, "date"]
  144. assert result == expected
  145. def test_mixed_index_at_iat_loc_iloc_series(self):
  146. # GH 19860
  147. s = Series([1, 2, 3, 4, 5], index=["a", "b", "c", 1, 2])
  148. for el, item in s.items():
  149. assert s.at[el] == s.loc[el] == item
  150. for i in range(len(s)):
  151. assert s.iat[i] == s.iloc[i] == i + 1
  152. with pytest.raises(KeyError, match="^4$"):
  153. s.at[4]
  154. with pytest.raises(KeyError, match="^4$"):
  155. s.loc[4]
  156. def test_mixed_index_at_iat_loc_iloc_dataframe(self):
  157. # GH 19860
  158. df = DataFrame(
  159. [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], columns=["a", "b", "c", 1, 2]
  160. )
  161. for rowIdx, row in df.iterrows():
  162. for el, item in row.items():
  163. assert df.at[rowIdx, el] == df.loc[rowIdx, el] == item
  164. for row in range(2):
  165. for i in range(5):
  166. assert df.iat[row, i] == df.iloc[row, i] == row * 5 + i
  167. with pytest.raises(KeyError, match="^3$"):
  168. df.at[0, 3]
  169. with pytest.raises(KeyError, match="^3$"):
  170. df.loc[0, 3]
  171. def test_iat_setter_incompatible_assignment(self):
  172. # GH 23236
  173. result = DataFrame({"a": [0.0, 1.0], "b": [4, 5]})
  174. result.iat[0, 0] = None
  175. expected = DataFrame({"a": [None, 1], "b": [4, 5]})
  176. tm.assert_frame_equal(result, expected)
  177. def test_iat_dont_wrap_object_datetimelike():
  178. # GH#32809 .iat calls go through DataFrame._get_value, should not
  179. # call maybe_box_datetimelike
  180. dti = date_range("2016-01-01", periods=3)
  181. tdi = dti - dti
  182. ser = Series(dti.to_pydatetime(), dtype=object)
  183. ser2 = Series(tdi.to_pytimedelta(), dtype=object)
  184. df = DataFrame({"A": ser, "B": ser2})
  185. assert (df.dtypes == object).all()
  186. for result in [df.at[0, "A"], df.iat[0, 0], df.loc[0, "A"], df.iloc[0, 0]]:
  187. assert result is ser[0]
  188. assert isinstance(result, datetime)
  189. assert not isinstance(result, Timestamp)
  190. for result in [df.at[1, "B"], df.iat[1, 1], df.loc[1, "B"], df.iloc[1, 1]]:
  191. assert result is ser2[1]
  192. assert isinstance(result, timedelta)
  193. assert not isinstance(result, Timedelta)
  194. def test_at_with_tuple_index_get():
  195. # GH 26989
  196. # DataFrame.at getter works with Index of tuples
  197. df = DataFrame({"a": [1, 2]}, index=[(1, 2), (3, 4)])
  198. assert df.index.nlevels == 1
  199. assert df.at[(1, 2), "a"] == 1
  200. # Series.at getter works with Index of tuples
  201. series = df["a"]
  202. assert series.index.nlevels == 1
  203. assert series.at[(1, 2)] == 1
  204. @pytest.mark.filterwarnings("ignore:Setting a value on a view:FutureWarning")
  205. def test_at_with_tuple_index_set():
  206. # GH 26989
  207. # DataFrame.at setter works with Index of tuples
  208. df = DataFrame({"a": [1, 2]}, index=[(1, 2), (3, 4)])
  209. assert df.index.nlevels == 1
  210. df.at[(1, 2), "a"] = 2
  211. assert df.at[(1, 2), "a"] == 2
  212. # Series.at setter works with Index of tuples
  213. series = df["a"]
  214. assert series.index.nlevels == 1
  215. series.at[1, 2] = 3
  216. assert series.at[1, 2] == 3
  217. class TestMultiIndexScalar:
  218. def test_multiindex_at_get(self):
  219. # GH 26989
  220. # DataFrame.at and DataFrame.loc getter works with MultiIndex
  221. df = DataFrame({"a": [1, 2]}, index=[[1, 2], [3, 4]])
  222. assert df.index.nlevels == 2
  223. assert df.at[(1, 3), "a"] == 1
  224. assert df.loc[(1, 3), "a"] == 1
  225. # Series.at and Series.loc getter works with MultiIndex
  226. series = df["a"]
  227. assert series.index.nlevels == 2
  228. assert series.at[1, 3] == 1
  229. assert series.loc[1, 3] == 1
  230. @pytest.mark.filterwarnings("ignore:Setting a value on a view:FutureWarning")
  231. def test_multiindex_at_set(self):
  232. # GH 26989
  233. # DataFrame.at and DataFrame.loc setter works with MultiIndex
  234. df = DataFrame({"a": [1, 2]}, index=[[1, 2], [3, 4]])
  235. assert df.index.nlevels == 2
  236. df.at[(1, 3), "a"] = 3
  237. assert df.at[(1, 3), "a"] == 3
  238. df.loc[(1, 3), "a"] = 4
  239. assert df.loc[(1, 3), "a"] == 4
  240. # Series.at and Series.loc setter works with MultiIndex
  241. series = df["a"]
  242. assert series.index.nlevels == 2
  243. series.at[1, 3] = 5
  244. assert series.at[1, 3] == 5
  245. series.loc[1, 3] = 6
  246. assert series.loc[1, 3] == 6
  247. def test_multiindex_at_get_one_level(self):
  248. # GH#38053
  249. s2 = Series((0, 1), index=[[False, True]])
  250. result = s2.at[False]
  251. assert result == 0