167 lines
5.3 KiB
Python
167 lines
5.3 KiB
Python
import operator
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
import pandas as pd
|
|
import pandas.util.testing as tm
|
|
from .base import BaseExtensionTests
|
|
|
|
|
|
class BaseSetitemTests(BaseExtensionTests):
|
|
def test_setitem_scalar_series(self, data):
|
|
arr = pd.Series(data)
|
|
arr[0] = data[1]
|
|
assert arr[0] == data[1]
|
|
|
|
def test_setitem_sequence(self, data):
|
|
arr = pd.Series(data)
|
|
original = data.copy()
|
|
|
|
arr[[0, 1]] = [data[1], data[0]]
|
|
assert arr[0] == original[1]
|
|
assert arr[1] == original[0]
|
|
|
|
@pytest.mark.parametrize('as_array', [True, False])
|
|
def test_setitem_sequence_mismatched_length_raises(self, data, as_array):
|
|
ser = pd.Series(data)
|
|
value = [data[0]]
|
|
if as_array:
|
|
value = data._from_sequence(value)
|
|
|
|
xpr = 'cannot set using a {} indexer with a different length'
|
|
with tm.assert_raises_regex(ValueError, xpr.format('list-like')):
|
|
ser[[0, 1]] = value
|
|
|
|
with tm.assert_raises_regex(ValueError, xpr.format('slice')):
|
|
ser[slice(3)] = value
|
|
|
|
def test_setitem_empty_indxer(self, data):
|
|
ser = pd.Series(data)
|
|
original = ser.copy()
|
|
ser[[]] = []
|
|
self.assert_series_equal(ser, original)
|
|
|
|
def test_setitem_sequence_broadcasts(self, data):
|
|
arr = pd.Series(data)
|
|
|
|
arr[[0, 1]] = data[2]
|
|
assert arr[0] == data[2]
|
|
assert arr[1] == data[2]
|
|
|
|
@pytest.mark.parametrize('setter', ['loc', 'iloc'])
|
|
def test_setitem_scalar(self, data, setter):
|
|
arr = pd.Series(data)
|
|
setter = getattr(arr, setter)
|
|
operator.setitem(setter, 0, data[1])
|
|
assert arr[0] == data[1]
|
|
|
|
def test_setitem_loc_scalar_mixed(self, data):
|
|
df = pd.DataFrame({"A": np.arange(len(data)), "B": data})
|
|
df.loc[0, 'B'] = data[1]
|
|
assert df.loc[0, 'B'] == data[1]
|
|
|
|
def test_setitem_loc_scalar_single(self, data):
|
|
df = pd.DataFrame({"B": data})
|
|
df.loc[10, 'B'] = data[1]
|
|
assert df.loc[10, 'B'] == data[1]
|
|
|
|
def test_setitem_loc_scalar_multiple_homogoneous(self, data):
|
|
df = pd.DataFrame({"A": data, "B": data})
|
|
df.loc[10, 'B'] = data[1]
|
|
assert df.loc[10, 'B'] == data[1]
|
|
|
|
def test_setitem_iloc_scalar_mixed(self, data):
|
|
df = pd.DataFrame({"A": np.arange(len(data)), "B": data})
|
|
df.iloc[0, 1] = data[1]
|
|
assert df.loc[0, 'B'] == data[1]
|
|
|
|
def test_setitem_iloc_scalar_single(self, data):
|
|
df = pd.DataFrame({"B": data})
|
|
df.iloc[10, 0] = data[1]
|
|
assert df.loc[10, 'B'] == data[1]
|
|
|
|
def test_setitem_iloc_scalar_multiple_homogoneous(self, data):
|
|
df = pd.DataFrame({"A": data, "B": data})
|
|
df.iloc[10, 1] = data[1]
|
|
assert df.loc[10, 'B'] == data[1]
|
|
|
|
@pytest.mark.parametrize('as_callable', [True, False])
|
|
@pytest.mark.parametrize('setter', ['loc', None])
|
|
def test_setitem_mask_aligned(self, data, as_callable, setter):
|
|
ser = pd.Series(data)
|
|
mask = np.zeros(len(data), dtype=bool)
|
|
mask[:2] = True
|
|
|
|
if as_callable:
|
|
mask2 = lambda x: mask
|
|
else:
|
|
mask2 = mask
|
|
|
|
if setter:
|
|
# loc
|
|
target = getattr(ser, setter)
|
|
else:
|
|
# Series.__setitem__
|
|
target = ser
|
|
|
|
operator.setitem(target, mask2, data[5:7])
|
|
|
|
ser[mask2] = data[5:7]
|
|
assert ser[0] == data[5]
|
|
assert ser[1] == data[6]
|
|
|
|
@pytest.mark.parametrize('setter', ['loc', None])
|
|
def test_setitem_mask_broadcast(self, data, setter):
|
|
ser = pd.Series(data)
|
|
mask = np.zeros(len(data), dtype=bool)
|
|
mask[:2] = True
|
|
|
|
if setter: # loc
|
|
target = getattr(ser, setter)
|
|
else: # __setitem__
|
|
target = ser
|
|
|
|
operator.setitem(target, mask, data[10])
|
|
assert ser[0] == data[10]
|
|
assert ser[1] == data[10]
|
|
|
|
def test_setitem_expand_columns(self, data):
|
|
df = pd.DataFrame({"A": data})
|
|
result = df.copy()
|
|
result['B'] = 1
|
|
expected = pd.DataFrame({"A": data, "B": [1] * len(data)})
|
|
self.assert_frame_equal(result, expected)
|
|
|
|
result = df.copy()
|
|
result.loc[:, 'B'] = 1
|
|
self.assert_frame_equal(result, expected)
|
|
|
|
# overwrite with new type
|
|
result['B'] = data
|
|
expected = pd.DataFrame({"A": data, "B": data})
|
|
self.assert_frame_equal(result, expected)
|
|
|
|
def test_setitem_expand_with_extension(self, data):
|
|
df = pd.DataFrame({"A": [1] * len(data)})
|
|
result = df.copy()
|
|
result['B'] = data
|
|
expected = pd.DataFrame({"A": [1] * len(data), "B": data})
|
|
self.assert_frame_equal(result, expected)
|
|
|
|
result = df.copy()
|
|
result.loc[:, 'B'] = data
|
|
self.assert_frame_equal(result, expected)
|
|
|
|
def test_setitem_frame_invalid_length(self, data):
|
|
df = pd.DataFrame({"A": [1] * len(data)})
|
|
xpr = "Length of values does not match length of index"
|
|
with tm.assert_raises_regex(ValueError, xpr):
|
|
df['B'] = data[:5]
|
|
|
|
@pytest.mark.xfail(reason="GH-20441: setitem on extension types.")
|
|
def test_setitem_tuple_index(self, data):
|
|
s = pd.Series(data[:2], index=[(0, 0), (0, 1)])
|
|
expected = pd.Series(data.take([1, 1]), index=s.index)
|
|
s[(0, 1)] = data[1]
|
|
self.assert_series_equal(s, expected)
|