Sam Chaudry
Upload folder using huggingface_hub
7885a28 verified
raw
history blame
20.8 kB
import contextlib
import pytest
import numpy as np
from numpy.testing import assert_allclose, assert_equal
from scipy.sparse import csr_array, dok_array, SparseEfficiencyWarning
from .test_arithmetic1d import toarray
formats_for_index1d = [csr_array, dok_array]
@contextlib.contextmanager
def check_remains_sorted(X):
"""Checks that sorted indices property is retained through an operation"""
yield
if not hasattr(X, 'has_sorted_indices') or not X.has_sorted_indices:
return
indices = X.indices.copy()
X.has_sorted_indices = False
X.sort_indices()
assert_equal(indices, X.indices, 'Expected sorted indices, found unsorted')
@pytest.mark.parametrize("spcreator", formats_for_index1d)
class TestGetSet1D:
def test_None_index(self, spcreator):
D = np.array([4, 3, 0])
A = spcreator(D)
N = D.shape[0]
for j in range(-N, N):
assert_equal(A[j, None].toarray(), D[j, None])
assert_equal(A[None, j].toarray(), D[None, j])
assert_equal(A[None, None, j].toarray(), D[None, None, j])
def test_getitem_shape(self, spcreator):
A = spcreator(np.arange(3 * 4).reshape(3, 4))
assert A[1, 2].ndim == 0
assert A[1, 2:3].shape == (1,)
assert A[None, 1, 2:3].shape == (1, 1)
assert A[None, 1, 2].shape == (1,)
assert A[None, 1, 2, None].shape == (1, 1)
# see gh-22458
assert A[None, 1].shape == (1, 4)
assert A[1, None].shape == (1, 4)
assert A[None, 1, :].shape == (1, 4)
assert A[1, None, :].shape == (1, 4)
assert A[1, :, None].shape == (4, 1)
with pytest.raises(IndexError, match='Only 1D or 2D arrays'):
A[None, 2, 1, None, None]
with pytest.raises(IndexError, match='Only 1D or 2D arrays'):
A[None, 0:2, None, 1]
with pytest.raises(IndexError, match='Only 1D or 2D arrays'):
A[0:1, 1:, None]
with pytest.raises(IndexError, match='Only 1D or 2D arrays'):
A[1:, 1, None, None]
def test_getelement(self, spcreator):
D = np.array([4, 3, 0])
A = spcreator(D)
N = D.shape[0]
for j in range(-N, N):
assert_equal(A[j], D[j])
for ij in [3, -4]:
with pytest.raises(IndexError, match='index (.*) out of (range|bounds)'):
A.__getitem__(ij)
# single element tuples unwrapped
assert A[(0,)] == 4
with pytest.raises(IndexError, match='index (.*) out of (range|bounds)'):
A.__getitem__((4,))
def test_setelement(self, spcreator):
dtype = np.float64
A = spcreator((12,), dtype=dtype)
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
A[0] = dtype(0)
A[1] = dtype(3)
A[8] = dtype(9.0)
A[-2] = dtype(7)
A[5] = 9
A[-9,] = dtype(8)
A[1,] = dtype(5) # overwrite using 1-tuple index
for ij in [13, -14, (13,), (14,)]:
with pytest.raises(IndexError, match='out of (range|bounds)'):
A.__setitem__(ij, 123.0)
@pytest.mark.parametrize("spcreator", formats_for_index1d)
class TestSlicingAndFancy1D:
#######################
# Int-like Array Index
#######################
def test_get_array_index(self, spcreator):
D = np.array([4, 3, 0])
A = spcreator(D)
assert_equal(A[()].toarray(), D[()])
for ij in [(0, 3), (3,)]:
with pytest.raises(IndexError, match='out of (range|bounds)|many indices'):
A.__getitem__(ij)
def test_set_array_index(self, spcreator):
dtype = np.float64
A = spcreator((12,), dtype=dtype)
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
A[np.array(6)] = dtype(4.0) # scalar index
A[np.array(6)] = dtype(2.0) # overwrite with scalar index
assert_equal(A.toarray(), [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0])
for ij in [(13,), (-14,)]:
with pytest.raises(IndexError, match='index .* out of (range|bounds)'):
A.__setitem__(ij, 123.0)
for v in [(), (0, 3), [1, 2, 3], np.array([1, 2, 3])]:
msg = 'Trying to assign a sequence to an item'
with pytest.raises(ValueError, match=msg):
A.__setitem__(0, v)
####################
# 1d Slice as index
####################
def test_dtype_preservation(self, spcreator):
assert_equal(spcreator((10,), dtype=np.int16)[1:5].dtype, np.int16)
assert_equal(spcreator((6,), dtype=np.int32)[0:0:2].dtype, np.int32)
assert_equal(spcreator((6,), dtype=np.int64)[:].dtype, np.int64)
def test_get_1d_slice(self, spcreator):
B = np.arange(50.)
A = spcreator(B)
assert_equal(B[:], A[:].toarray())
assert_equal(B[2:5], A[2:5].toarray())
C = np.array([4, 0, 6, 0, 0, 0, 0, 0, 1])
D = spcreator(C)
assert_equal(C[1:3], D[1:3].toarray())
# Now test slicing when a row contains only zeros
E = np.array([0, 0, 0, 0, 0])
F = spcreator(E)
assert_equal(E[1:3], F[1:3].toarray())
assert_equal(E[-2:], F[-2:].toarray())
assert_equal(E[:], F[:].toarray())
assert_equal(E[slice(None)], F[slice(None)].toarray())
def test_slicing_idx_slice(self, spcreator):
B = np.arange(50)
A = spcreator(B)
# [i]
assert_equal(A[2], B[2])
assert_equal(A[-1], B[-1])
assert_equal(A[np.array(-2)], B[-2])
# [1:2]
assert_equal(A[:].toarray(), B[:])
assert_equal(A[5:-2].toarray(), B[5:-2])
assert_equal(A[5:12:3].toarray(), B[5:12:3])
# int8 slice
s = slice(np.int8(2), np.int8(4), None)
assert_equal(A[s].toarray(), B[2:4])
# np.s_
s_ = np.s_
slices = [s_[:2], s_[1:2], s_[3:], s_[3::2],
s_[15:20], s_[3:2],
s_[8:3:-1], s_[4::-2], s_[:5:-1],
0, 1, s_[:], s_[1:5], -1, -2, -5,
np.array(-1), np.int8(-3)]
for j, a in enumerate(slices):
x = A[a]
y = B[a]
if y.shape == ():
assert_equal(x, y, repr(a))
else:
if x.size == 0 and y.size == 0:
pass
else:
assert_equal(x.toarray(), y, repr(a))
def test_ellipsis_1d_slicing(self, spcreator):
B = np.arange(50)
A = spcreator(B)
assert_equal(A[...].toarray(), B[...])
assert_equal(A[...,].toarray(), B[...,])
##########################
# Assignment with Slicing
##########################
def test_slice_scalar_assign(self, spcreator):
A = spcreator((5,))
B = np.zeros((5,))
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
for C in [A, B]:
C[0:1] = 1
C[2:0] = 4
C[2:3] = 9
C[3:] = 1
C[3::-1] = 9
assert_equal(A.toarray(), B)
def test_slice_assign_2(self, spcreator):
shape = (10,)
for idx in [slice(3), slice(None, 10, 4), slice(5, -2)]:
A = spcreator(shape)
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
A[idx] = 1
B = np.zeros(shape)
B[idx] = 1
msg = f"idx={idx!r}"
assert_allclose(A.toarray(), B, err_msg=msg)
def test_self_self_assignment(self, spcreator):
# Tests whether a row of one lil_matrix can be assigned to another.
B = spcreator((5,))
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
B[0] = 2
B[1] = 0
B[2] = 3
B[3] = 10
A = B / 10
B[:] = A[:]
assert_equal(A[:].toarray(), B[:].toarray())
A = B / 10
B[:] = A[:1]
assert_equal(np.zeros((5,)) + A[0], B.toarray())
A = B / 10
B[:-1] = A[1:]
assert_equal(A[1:].toarray(), B[:-1].toarray())
def test_slice_assignment(self, spcreator):
B = spcreator((4,))
expected = np.array([10, 0, 14, 0])
block = [2, 1]
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
B[0] = 5
B[2] = 7
B[:] = B + B
assert_equal(B.toarray(), expected)
B[:2] = csr_array(block)
assert_equal(B.toarray()[:2], block)
def test_set_slice(self, spcreator):
A = spcreator((5,))
B = np.zeros(5, float)
s_ = np.s_
slices = [s_[:2], s_[1:2], s_[3:], s_[3::2],
s_[8:3:-1], s_[4::-2], s_[:5:-1],
0, 1, s_[:], s_[1:5], -1, -2, -5,
np.array(-1), np.int8(-3)]
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
for j, a in enumerate(slices):
A[a] = j
B[a] = j
assert_equal(A.toarray(), B, repr(a))
A[1:10:2] = range(1, 5, 2)
B[1:10:2] = range(1, 5, 2)
assert_equal(A.toarray(), B)
# The next commands should raise exceptions
toobig = list(range(100))
with pytest.raises(ValueError, match='Trying to assign a sequence to an item'):
A.__setitem__(0, toobig)
with pytest.raises(ValueError, match='could not be broadcast together'):
A.__setitem__(slice(None), toobig)
def test_assign_empty(self, spcreator):
A = spcreator(np.ones(3))
B = spcreator((2,))
A[:2] = B
assert_equal(A.toarray(), [0, 0, 1])
####################
# 1d Fancy Indexing
####################
def test_dtype_preservation_empty_index(self, spcreator):
A = spcreator((2,), dtype=np.int16)
assert_equal(A[[False, False]].dtype, np.int16)
assert_equal(A[[]].dtype, np.int16)
def test_bad_index(self, spcreator):
A = spcreator(np.zeros(5))
with pytest.raises(
(IndexError, ValueError, TypeError),
match='Index dimension must be 1 or 2|only integers',
):
A.__getitem__("foo")
with pytest.raises(
(IndexError, ValueError, TypeError),
match='tuple index out of range|only integers',
):
A.__getitem__((2, "foo"))
def test_fancy_indexing_2darray(self, spcreator):
B = np.arange(50).reshape((5, 10))
A = spcreator(B)
# [i]
assert_equal(A[[1, 3]].toarray(), B[[1, 3]])
# [i,[1,2]]
assert_equal(A[3, [1, 3]].toarray(), B[3, [1, 3]])
assert_equal(A[-1, [2, -5]].toarray(), B[-1, [2, -5]])
assert_equal(A[np.array(-1), [2, -5]].toarray(), B[-1, [2, -5]])
assert_equal(A[-1, np.array([2, -5])].toarray(), B[-1, [2, -5]])
assert_equal(A[np.array(-1), np.array([2, -5])].toarray(), B[-1, [2, -5]])
# [1:2,[1,2]]
assert_equal(A[:, [2, 8, 3, -1]].toarray(), B[:, [2, 8, 3, -1]])
assert_equal(A[3:4, [9]].toarray(), B[3:4, [9]])
assert_equal(A[1:4, [-1, -5]].toarray(), B[1:4, [-1, -5]])
assert_equal(A[1:4, np.array([-1, -5])].toarray(), B[1:4, [-1, -5]])
# [[1,2],j]
assert_equal(A[[1, 3], 3].toarray(), B[[1, 3], 3])
assert_equal(A[[2, -5], -4].toarray(), B[[2, -5], -4])
assert_equal(A[np.array([2, -5]), -4].toarray(), B[[2, -5], -4])
assert_equal(A[[2, -5], np.array(-4)].toarray(), B[[2, -5], -4])
assert_equal(A[np.array([2, -5]), np.array(-4)].toarray(), B[[2, -5], -4])
# [[1,2],1:2]
assert_equal(A[[1, 3], :].toarray(), B[[1, 3], :])
assert_equal(A[[2, -5], 8:-1].toarray(), B[[2, -5], 8:-1])
assert_equal(A[np.array([2, -5]), 8:-1].toarray(), B[[2, -5], 8:-1])
# [[1,2],[1,2]]
assert_equal(toarray(A[[1, 3], [2, 4]]), B[[1, 3], [2, 4]])
assert_equal(toarray(A[[-1, -3], [2, -4]]), B[[-1, -3], [2, -4]])
assert_equal(
toarray(A[np.array([-1, -3]), [2, -4]]), B[[-1, -3], [2, -4]]
)
assert_equal(
toarray(A[[-1, -3], np.array([2, -4])]), B[[-1, -3], [2, -4]]
)
assert_equal(
toarray(A[np.array([-1, -3]), np.array([2, -4])]), B[[-1, -3], [2, -4]]
)
# [[[1],[2]],[1,2]]
assert_equal(A[[[1], [3]], [2, 4]].toarray(), B[[[1], [3]], [2, 4]])
assert_equal(
A[[[-1], [-3], [-2]], [2, -4]].toarray(),
B[[[-1], [-3], [-2]], [2, -4]]
)
assert_equal(
A[np.array([[-1], [-3], [-2]]), [2, -4]].toarray(),
B[[[-1], [-3], [-2]], [2, -4]]
)
assert_equal(
A[[[-1], [-3], [-2]], np.array([2, -4])].toarray(),
B[[[-1], [-3], [-2]], [2, -4]]
)
assert_equal(
A[np.array([[-1], [-3], [-2]]), np.array([2, -4])].toarray(),
B[[[-1], [-3], [-2]], [2, -4]]
)
# [[1,2]]
assert_equal(A[[1, 3]].toarray(), B[[1, 3]])
assert_equal(A[[-1, -3]].toarray(), B[[-1, -3]])
assert_equal(A[np.array([-1, -3])].toarray(), B[[-1, -3]])
# [[1,2],:][:,[1,2]]
assert_equal(
A[[1, 3], :][:, [2, 4]].toarray(), B[[1, 3], :][:, [2, 4]]
)
assert_equal(
A[[-1, -3], :][:, [2, -4]].toarray(), B[[-1, -3], :][:, [2, -4]]
)
assert_equal(
A[np.array([-1, -3]), :][:, np.array([2, -4])].toarray(),
B[[-1, -3], :][:, [2, -4]]
)
# [:,[1,2]][[1,2],:]
assert_equal(
A[:, [1, 3]][[2, 4], :].toarray(), B[:, [1, 3]][[2, 4], :]
)
assert_equal(
A[:, [-1, -3]][[2, -4], :].toarray(), B[:, [-1, -3]][[2, -4], :]
)
assert_equal(
A[:, np.array([-1, -3])][np.array([2, -4]), :].toarray(),
B[:, [-1, -3]][[2, -4], :]
)
def test_fancy_indexing(self, spcreator):
B = np.arange(50)
A = spcreator(B)
# [i]
assert_equal(A[[3]].toarray(), B[[3]])
# [np.array]
assert_equal(A[[1, 3]].toarray(), B[[1, 3]])
assert_equal(A[[2, -5]].toarray(), B[[2, -5]])
assert_equal(A[np.array(-1)], B[-1])
assert_equal(A[np.array([-1, 2])].toarray(), B[[-1, 2]])
assert_equal(A[np.array(5)], B[np.array(5)])
# [[[1],[2]]]
ind = np.array([[1], [3]])
assert_equal(A[ind].toarray(), B[ind])
ind = np.array([[-1], [-3], [-2]])
assert_equal(A[ind].toarray(), B[ind])
# [[1, 2]]
assert_equal(A[[1, 3]].toarray(), B[[1, 3]])
assert_equal(A[[-1, -3]].toarray(), B[[-1, -3]])
assert_equal(A[np.array([-1, -3])].toarray(), B[[-1, -3]])
# [[1, 2]][[1, 2]]
assert_equal(A[[1, 5, 2, 8]][[1, 3]].toarray(),
B[[1, 5, 2, 8]][[1, 3]])
assert_equal(A[[-1, -5, 2, 8]][[1, -4]].toarray(),
B[[-1, -5, 2, 8]][[1, -4]])
def test_fancy_indexing_boolean(self, spcreator):
np.random.seed(1234) # make runs repeatable
B = np.arange(50)
A = spcreator(B)
I = np.array(np.random.randint(0, 2, size=50), dtype=bool)
assert_equal(toarray(A[I]), B[I])
assert_equal(toarray(A[B > 9]), B[B > 9])
Z1 = np.zeros(51, dtype=bool)
Z2 = np.zeros(51, dtype=bool)
Z2[-1] = True
Z3 = np.zeros(51, dtype=bool)
Z3[0] = True
msg = 'bool index .* has shape|boolean index did not match'
with pytest.raises(IndexError, match=msg):
A.__getitem__(Z1)
with pytest.raises(IndexError, match=msg):
A.__getitem__(Z2)
with pytest.raises(IndexError, match=msg):
A.__getitem__(Z3)
def test_fancy_indexing_sparse_boolean(self, spcreator):
np.random.seed(1234) # make runs repeatable
B = np.arange(20)
A = spcreator(B)
X = np.array(np.random.randint(0, 2, size=20), dtype=bool)
Xsp = csr_array(X)
assert_equal(toarray(A[Xsp]), B[X])
assert_equal(toarray(A[A > 9]), B[B > 9])
Y = np.array(np.random.randint(0, 2, size=60), dtype=bool)
Ysp = csr_array(Y)
with pytest.raises(IndexError, match='bool index .* has shape|only integers'):
A.__getitem__(Ysp)
with pytest.raises(IndexError, match='tuple index out of range|only integers'):
A.__getitem__((Xsp, 1))
def test_fancy_indexing_seq_assign(self, spcreator):
mat = spcreator(np.array([1, 0]))
with pytest.raises(ValueError, match='Trying to assign a sequence to an item'):
mat.__setitem__(0, np.array([1, 2]))
def test_fancy_indexing_empty(self, spcreator):
B = np.arange(50)
B[3:9] = 0
B[30] = 0
A = spcreator(B)
K = np.array([False] * 50)
assert_equal(toarray(A[K]), B[K])
K = np.array([], dtype=int)
assert_equal(toarray(A[K]), B[K])
J = np.array([0, 1, 2, 3, 4], dtype=int)
assert_equal(toarray(A[J]), B[J])
############################
# 1d Fancy Index Assignment
############################
def test_bad_index_assign(self, spcreator):
A = spcreator(np.zeros(5))
msg = 'Index dimension must be 1 or 2|only integers'
with pytest.raises((IndexError, ValueError, TypeError), match=msg):
A.__setitem__("foo", 2)
def test_fancy_indexing_set(self, spcreator):
M = (5,)
# [1:2]
for j in [[2, 3, 4], slice(None, 10, 4), np.arange(3),
slice(5, -2), slice(2, 5)]:
A = spcreator(M)
B = np.zeros(M)
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
B[j] = 1
with check_remains_sorted(A):
A[j] = 1
assert_allclose(A.toarray(), B)
def test_sequence_assignment(self, spcreator):
A = spcreator((4,))
B = spcreator((3,))
i0 = [0, 1, 2]
i1 = (0, 1, 2)
i2 = np.array(i0)
with np.testing.suppress_warnings() as sup:
sup.filter(
SparseEfficiencyWarning,
"Changing the sparsity structure of .* is expensive",
)
with check_remains_sorted(A):
A[i0] = B[i0]
msg = "too many indices for array|tuple index out of range"
with pytest.raises(IndexError, match=msg):
B.__getitem__(i1)
A[i2] = B[i2]
assert_equal(A[:3].toarray(), B.toarray())
assert A.shape == (4,)
# slice
A = spcreator((4,))
with check_remains_sorted(A):
A[1:3] = [10, 20]
assert_equal(A.toarray(), [0, 10, 20, 0])
# array
A = spcreator((4,))
B = np.zeros(4)
with check_remains_sorted(A):
for C in [A, B]:
C[[0, 1, 2]] = [4, 5, 6]
assert_equal(A.toarray(), B)
def test_fancy_assign_empty(self, spcreator):
B = np.arange(50)
B[2] = 0
B[[3, 6]] = 0
A = spcreator(B)
K = np.array([False] * 50)
A[K] = 42
assert_equal(A.toarray(), B)
K = np.array([], dtype=int)
A[K] = 42
assert_equal(A.toarray(), B)