setitem.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import operator
  2. import numpy as np
  3. import pytest
  4. import pandas as pd
  5. from .base import BaseExtensionTests
  6. class BaseSetitemTests(BaseExtensionTests):
  7. def test_setitem_scalar_series(self, data, box_in_series):
  8. if box_in_series:
  9. data = pd.Series(data)
  10. data[0] = data[1]
  11. assert data[0] == data[1]
  12. def test_setitem_sequence(self, data, box_in_series):
  13. if box_in_series:
  14. data = pd.Series(data)
  15. original = data.copy()
  16. data[[0, 1]] = [data[1], data[0]]
  17. assert data[0] == original[1]
  18. assert data[1] == original[0]
  19. @pytest.mark.parametrize('as_array', [True, False])
  20. def test_setitem_sequence_mismatched_length_raises(self, data, as_array):
  21. ser = pd.Series(data)
  22. original = ser.copy()
  23. value = [data[0]]
  24. if as_array:
  25. value = data._from_sequence(value)
  26. xpr = 'cannot set using a {} indexer with a different length'
  27. with pytest.raises(ValueError, match=xpr.format('list-like')):
  28. ser[[0, 1]] = value
  29. # Ensure no modifications made before the exception
  30. self.assert_series_equal(ser, original)
  31. with pytest.raises(ValueError, match=xpr.format('slice')):
  32. ser[slice(3)] = value
  33. self.assert_series_equal(ser, original)
  34. def test_setitem_empty_indxer(self, data, box_in_series):
  35. if box_in_series:
  36. data = pd.Series(data)
  37. original = data.copy()
  38. data[np.array([], dtype=int)] = []
  39. self.assert_equal(data, original)
  40. def test_setitem_sequence_broadcasts(self, data, box_in_series):
  41. if box_in_series:
  42. data = pd.Series(data)
  43. data[[0, 1]] = data[2]
  44. assert data[0] == data[2]
  45. assert data[1] == data[2]
  46. @pytest.mark.parametrize('setter', ['loc', 'iloc'])
  47. def test_setitem_scalar(self, data, setter):
  48. arr = pd.Series(data)
  49. setter = getattr(arr, setter)
  50. operator.setitem(setter, 0, data[1])
  51. assert arr[0] == data[1]
  52. def test_setitem_loc_scalar_mixed(self, data):
  53. df = pd.DataFrame({"A": np.arange(len(data)), "B": data})
  54. df.loc[0, 'B'] = data[1]
  55. assert df.loc[0, 'B'] == data[1]
  56. def test_setitem_loc_scalar_single(self, data):
  57. df = pd.DataFrame({"B": data})
  58. df.loc[10, 'B'] = data[1]
  59. assert df.loc[10, 'B'] == data[1]
  60. def test_setitem_loc_scalar_multiple_homogoneous(self, data):
  61. df = pd.DataFrame({"A": data, "B": data})
  62. df.loc[10, 'B'] = data[1]
  63. assert df.loc[10, 'B'] == data[1]
  64. def test_setitem_iloc_scalar_mixed(self, data):
  65. df = pd.DataFrame({"A": np.arange(len(data)), "B": data})
  66. df.iloc[0, 1] = data[1]
  67. assert df.loc[0, 'B'] == data[1]
  68. def test_setitem_iloc_scalar_single(self, data):
  69. df = pd.DataFrame({"B": data})
  70. df.iloc[10, 0] = data[1]
  71. assert df.loc[10, 'B'] == data[1]
  72. def test_setitem_iloc_scalar_multiple_homogoneous(self, data):
  73. df = pd.DataFrame({"A": data, "B": data})
  74. df.iloc[10, 1] = data[1]
  75. assert df.loc[10, 'B'] == data[1]
  76. @pytest.mark.parametrize('as_callable', [True, False])
  77. @pytest.mark.parametrize('setter', ['loc', None])
  78. def test_setitem_mask_aligned(self, data, as_callable, setter):
  79. ser = pd.Series(data)
  80. mask = np.zeros(len(data), dtype=bool)
  81. mask[:2] = True
  82. if as_callable:
  83. mask2 = lambda x: mask
  84. else:
  85. mask2 = mask
  86. if setter:
  87. # loc
  88. target = getattr(ser, setter)
  89. else:
  90. # Series.__setitem__
  91. target = ser
  92. operator.setitem(target, mask2, data[5:7])
  93. ser[mask2] = data[5:7]
  94. assert ser[0] == data[5]
  95. assert ser[1] == data[6]
  96. @pytest.mark.parametrize('setter', ['loc', None])
  97. def test_setitem_mask_broadcast(self, data, setter):
  98. ser = pd.Series(data)
  99. mask = np.zeros(len(data), dtype=bool)
  100. mask[:2] = True
  101. if setter: # loc
  102. target = getattr(ser, setter)
  103. else: # __setitem__
  104. target = ser
  105. operator.setitem(target, mask, data[10])
  106. assert ser[0] == data[10]
  107. assert ser[1] == data[10]
  108. def test_setitem_expand_columns(self, data):
  109. df = pd.DataFrame({"A": data})
  110. result = df.copy()
  111. result['B'] = 1
  112. expected = pd.DataFrame({"A": data, "B": [1] * len(data)})
  113. self.assert_frame_equal(result, expected)
  114. result = df.copy()
  115. result.loc[:, 'B'] = 1
  116. self.assert_frame_equal(result, expected)
  117. # overwrite with new type
  118. result['B'] = data
  119. expected = pd.DataFrame({"A": data, "B": data})
  120. self.assert_frame_equal(result, expected)
  121. def test_setitem_expand_with_extension(self, data):
  122. df = pd.DataFrame({"A": [1] * len(data)})
  123. result = df.copy()
  124. result['B'] = data
  125. expected = pd.DataFrame({"A": [1] * len(data), "B": data})
  126. self.assert_frame_equal(result, expected)
  127. result = df.copy()
  128. result.loc[:, 'B'] = data
  129. self.assert_frame_equal(result, expected)
  130. def test_setitem_frame_invalid_length(self, data):
  131. df = pd.DataFrame({"A": [1] * len(data)})
  132. xpr = "Length of values does not match length of index"
  133. with pytest.raises(ValueError, match=xpr):
  134. df['B'] = data[:5]
  135. @pytest.mark.xfail(reason="GH#20441: setitem on extension types.")
  136. def test_setitem_tuple_index(self, data):
  137. s = pd.Series(data[:2], index=[(0, 0), (0, 1)])
  138. expected = pd.Series(data.take([1, 1]), index=s.index)
  139. s[(0, 1)] = data[1]
  140. self.assert_series_equal(s, expected)
  141. def test_setitem_slice_mismatch_length_raises(self, data):
  142. arr = data[:5]
  143. with pytest.raises(ValueError):
  144. arr[:1] = arr[:2]
  145. def test_setitem_slice_array(self, data):
  146. arr = data[:5].copy()
  147. arr[:5] = data[-5:]
  148. self.assert_extension_array_equal(arr, data[-5:])
  149. def test_setitem_scalar_key_sequence_raise(self, data):
  150. arr = data[:5].copy()
  151. with pytest.raises(ValueError):
  152. arr[0] = arr[[0, 1]]