NumPy 源码解析(十五)
.\numpy\numpy\lib\tests\test_loadtxt.py
"""
`np.loadtxt`的特定测试,用于在将loadtxt移至C代码后进行的补充测试。
这些测试是`test_io.py`中已有测试的补充。
"""
import sys
import os
import pytest
from tempfile import NamedTemporaryFile, mkstemp
from io import StringIO
import numpy as np
from numpy.ma.testutils import assert_equal
from numpy.testing import assert_array_equal, HAS_REFCOUNT, IS_PYPY
def test_scientific_notation():
"""测试科学计数法中 'e' 和 'E' 的解析是否正确。"""
data = StringIO(
(
"1.0e-1,2.0E1,3.0\n"
"4.0e-2,5.0E-1,6.0\n"
"7.0e-3,8.0E1,9.0\n"
"0.0e-4,1.0E-1,2.0"
)
)
expected = np.array(
[[0.1, 20., 3.0], [0.04, 0.5, 6], [0.007, 80., 9], [0, 0.1, 2]]
)
assert_array_equal(np.loadtxt(data, delimiter=","), expected)
@pytest.mark.parametrize("comment", ["..", "//", "@-", "this is a comment:"])
def test_comment_multiple_chars(comment):
"""测试多字符注释在加载数据时的处理。"""
content = "# IGNORE\n1.5, 2.5# ABC\n3.0,4.0# XXX\n5.5,6.0\n"
txt = StringIO(content.replace("#", comment))
a = np.loadtxt(txt, delimiter=",", comments=comment)
assert_equal(a, [[1.5, 2.5], [3.0, 4.0], [5.5, 6.0]])
@pytest.fixture
def mixed_types_structured():
"""
提供具有结构化dtype的异构输入数据和相关结构化数组的fixture。
"""
data = StringIO(
(
"1000;2.4;alpha;-34\n"
"2000;3.1;beta;29\n"
"3500;9.9;gamma;120\n"
"4090;8.1;delta;0\n"
"5001;4.4;epsilon;-99\n"
"6543;7.8;omega;-1\n"
)
)
dtype = np.dtype(
[('f0', np.uint16), ('f1', np.float64), ('f2', 'S7'), ('f3', np.int8)]
)
expected = np.array(
[
(1000, 2.4, "alpha", -34),
(2000, 3.1, "beta", 29),
(3500, 9.9, "gamma", 120),
(4090, 8.1, "delta", 0),
(5001, 4.4, "epsilon", -99),
(6543, 7.8, "omega", -1)
],
dtype=dtype
)
return data, dtype, expected
@pytest.mark.parametrize('skiprows', [0, 1, 2, 3])
def test_structured_dtype_and_skiprows_no_empty_lines(
skiprows, mixed_types_structured):
"""测试结构化dtype和跳过行数(无空行)的情况。"""
data, dtype, expected = mixed_types_structured
a = np.loadtxt(data, dtype=dtype, delimiter=";", skiprows=skiprows)
assert_array_equal(a, expected[skiprows:])
def test_unpack_structured(mixed_types_structured):
"""测试结构化dtype在解包时的处理。"""
data, dtype, expected = mixed_types_structured
a, b, c, d = np.loadtxt(data, dtype=dtype, delimiter=";", unpack=True)
assert_array_equal(a, expected["f0"])
assert_array_equal(b, expected["f1"])
assert_array_equal(c, expected["f2"])
assert_array_equal(d, expected["f3"])
def test_structured_dtype_with_shape():
"""测试带形状的结构化dtype的情况。"""
dtype = np.dtype([("a", "u1", 2), ("b", "u1", 2)])
data = StringIO("0,1,2,3\n6,7,8,9\n")
expected = np.array([((0, 1), (2, 3)), ((6, 7), (8, 9))], dtype=dtype)
assert_array_equal(np.loadtxt(data, delimiter=",", dtype=dtype), expected)
def test_structured_dtype_with_multi_shape():
dtype = np.dtype([("a", "u1", (2, 2))])
data = StringIO("0 1 2 3\n")
expected = np.array([(((0, 1), (2, 3)),)], dtype=dtype)
assert_array_equal(np.loadtxt(data, dtype=dtype), expected)
def test_nested_structured_subarray():
point = np.dtype([('x', float), ('y', float)])
dt = np.dtype([('code', int), ('points', point, (2,))])
data = StringIO("100,1,2,3,4\n200,5,6,7,8\n")
expected = np.array(
[
(100, [(1., 2.), (3., 4.)]),
(200, [(5., 6.), (7., 8.)]),
],
dtype=dt
)
assert_array_equal(np.loadtxt(data, dtype=dt, delimiter=","), expected)
def test_structured_dtype_offsets():
dt = np.dtype("i1, i4, i1, i4, i1, i4", align=True)
data = StringIO("1,2,3,4,5,6\n7,8,9,10,11,12\n")
expected = np.array([(1, 2, 3, 4, 5, 6), (7, 8, 9, 10, 11, 12)], dtype=dt)
assert_array_equal(np.loadtxt(data, delimiter=",", dtype=dt), expected)
@pytest.mark.parametrize("param", ("skiprows", "max_rows"))
def test_exception_negative_row_limits(param):
"""skiprows 和 max_rows 应当对负参数抛出异常。"""
with pytest.raises(ValueError, match="argument must be nonnegative"):
np.loadtxt("foo.bar", **{param: -3})
@pytest.mark.parametrize("param", ("skiprows", "max_rows"))
def test_exception_noninteger_row_limits(param):
with pytest.raises(TypeError, match="argument must be an integer"):
np.loadtxt("foo.bar", **{param: 1.0})
@pytest.mark.parametrize(
"data, shape",
[
("1 2 3 4 5\n", (1, 5)),
("1\n2\n3\n4\n5\n", (5, 1)),
]
)
def test_ndmin_single_row_or_col(data, shape):
arr = np.array([1, 2, 3, 4, 5])
arr2d = arr.reshape(shape)
assert_array_equal(np.loadtxt(StringIO(data), dtype=int), arr)
assert_array_equal(np.loadtxt(StringIO(data), dtype=int, ndmin=0), arr)
assert_array_equal(np.loadtxt(StringIO(data), dtype=int, ndmin=1), arr)
assert_array_equal(np.loadtxt(StringIO(data), dtype=int, ndmin=2), arr2d)
@pytest.mark.parametrize("badval", [-1, 3, None, "plate of shrimp"])
def test_bad_ndmin(badval):
with pytest.raises(ValueError, match="Illegal value of ndmin keyword"):
np.loadtxt("foo.bar", ndmin=badval)
@pytest.mark.parametrize(
"ws",
(
" ",
"\t",
"\u2003",
"\u00A0",
"\u3000",
)
)
def test_blank_lines_spaces_delimit(ws):
txt = StringIO(
f"1 2{ws}30\n\n{ws}\n"
f"4 5 60{ws}\n {ws} \n"
f"7 8 {ws} 90\n # comment\n"
f"3 2 1"
)
expected = np.array([[1, 2, 30], [4, 5, 60], [7, 8, 90], [3, 2, 1]])
assert_equal(
np.loadtxt(txt, dtype=int, delimiter=None, comments="#"),
expected
)
def test_blank_lines_normal_delimiter():
txt = StringIO('1,2,30\n\n4,5,60\n\n7,8,90\n# comment\n3,2,1')
expected = np.array([[1, 2, 30], [4, 5, 60], [7, 8, 90], [3, 2, 1]])
assert_equal(
np.loadtxt(txt, dtype=int, delimiter=',', comments="#"), expected
)
@pytest.mark.parametrize("dtype", (float, object))
def test_maxrows_no_blank_lines(dtype):
txt = StringIO("1.5,2.5\n3.0,4.0\n5.5,6.0")
res = np.loadtxt(txt, dtype=dtype, delimiter=",", max_rows=2)
assert_equal(res.dtype, dtype)
assert_equal(res, np.array([["1.5", "2.5"], ["3.0", "4.0"]], dtype=dtype))
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
@pytest.mark.parametrize("dtype", (np.dtype("f8"), np.dtype("i2")))
def test_exception_message_bad_values(dtype):
txt = StringIO("1,2\n3,XXX\n5,6")
msg = f"could not convert string 'XXX' to {dtype} at row 1, column 2"
with pytest.raises(ValueError, match=msg):
np.loadtxt(txt, dtype=dtype, delimiter=",")
def test_converters_negative_indices():
txt = StringIO('1.5,2.5\n3.0,XXX\n5.5,6.0')
conv = {-1: lambda s: np.nan if s == 'XXX' else float(s)}
expected = np.array([[1.5, 2.5], [3.0, np.nan], [5.5, 6.0]])
res = np.loadtxt(txt, dtype=np.float64, delimiter=",", converters=conv)
assert_equal(res, expected)
def test_converters_negative_indices_with_usecols():
txt = StringIO('1.5,2.5,3.5\n3.0,4.0,XXX\n5.5,6.0,7.5\n')
conv = {-1: lambda s: np.nan if s == 'XXX' else float(s)}
expected = np.array([[1.5, 3.5], [3.0, np.nan], [5.5, 7.5]])
res = np.loadtxt(
txt,
dtype=np.float64,
delimiter=",",
converters=conv,
usecols=[0, -1],
)
assert_equal(res, expected)
res = np.loadtxt(StringIO('''0,1,2\n0,1,2,3,4'''), delimiter=",",
usecols=[0, -1], converters={-1: (lambda x: -1)})
assert_array_equal(res, [[0, -1], [0, -1]])
def test_ragged_error():
rows = ["1,2,3", "1,2,3", "4,3,2,1"]
with pytest.raises(ValueError,
match="the number of columns changed from 3 to 4 at row 3"):
np.loadtxt(rows, delimiter=",")
def test_ragged_usecols():
txt = StringIO("0,0,XXX\n0,XXX,0,XXX\n0,XXX,XXX,0,XXX\n")
expected = np.array([[0, 0], [0, 0], [0, 0]])
res = np.loadtxt(txt, dtype=float, delimiter=",", usecols=[0, -2])
assert_equal(res, expected)
txt = StringIO("0,0,XXX\n0\n0,XXX,XXX,0,XXX\n")
with pytest.raises(ValueError,
match="invalid column index -2 at row 2 with 1 columns"):
np.loadtxt(txt, dtype=float, delimiter=",", usecols=[0, -2])
def test_empty_usecols():
txt = StringIO("0,0,XXX\n0,XXX,0,XXX\n0,XXX,XXX,0,XXX\n")
res = np.loadtxt(txt, dtype=np.dtype([]), delimiter=",", usecols=[])
assert res.shape == (3,)
assert res.dtype == np.dtype([])
@pytest.mark.parametrize("c1", ["a", "の", "🫕"])
@pytest.mark.parametrize("c2", ["a", "の", "🫕"])
def test_large_unicode_characters(c1, c2):
txt = StringIO(f"a,{c1},c,1.0\ne,{c2},2.0,g")
res = np.loadtxt(txt, dtype=np.dtype('U12'), delimiter=",")
expected = np.array(
[f"a,{c1},c,1.0".split(","), f"e,{c2},2.0,g".split(",")],
dtype=np.dtype('U12')
)
assert_equal(res, expected)
def test_unicode_with_converter():
txt = StringIO("cat,dog\nαβγ,δεζ\nabc,def\n")
conv = {0: lambda s: s.upper()}
res = np.loadtxt(
txt,
dtype=np.dtype("U12"),
converters=conv,
delimiter=",",
encoding=None
)
expected = np.array([['CAT', 'dog'], ['ΑΒΓ', 'δεζ'], ['ABC', 'def']])
assert_equal(res, expected)
def test_converter_with_structured_dtype():
txt = StringIO('1.5,2.5,Abc\n3.0,4.0,dEf\n5.5,6.0,ghI\n')
dt = np.dtype([('m', np.int32), ('r', np.float32), ('code', 'U8')])
conv = {0: lambda s: int(10*float(s)), -1: lambda s: s.upper()}
res = np.loadtxt(txt, dtype=dt, delimiter=",", converters=conv)
expected = np.array(
[(15, 2.5, 'ABC'), (30, 4.0, 'DEF'), (55, 6.0, 'GHI')], dtype=dt
)
assert_equal(res, expected)
def test_converter_with_unicode_dtype():
"""
当使用 'bytes' 编码时,标记 tokens 之前编码。这意味着转换器的输出可能是字节而不是 `read_rows` 预期的 Unicode。
此测试检查以上场景的输出是否在由 `read_rows` 解析之前被正确解码。
"""
txt = StringIO('abc,def\nrst,xyz')
conv = bytes.upper
res = np.loadtxt(
txt, dtype=np.dtype("U3"), converters=conv, delimiter=",",
encoding="bytes")
expected = np.array([['ABC', 'DEF'], ['RST', 'XYZ']])
assert_equal(res, expected)
def test_read_huge_row():
row = "1.5, 2.5," * 50000
row = row[:-1] + "\n"
txt = StringIO(row * 2)
res = np.loadtxt(txt, delimiter=",", dtype=float)
assert_equal(res, np.tile([1.5, 2.5], (2, 50000)))
@pytest.mark.parametrize("dtype", "edfgFDG")
def test_huge_float(dtype):
field = "0" * 1000 + ".123456789"
dtype = np.dtype(dtype)
value = np.loadtxt([field], dtype=dtype)[()]
assert value == dtype.type("0.123456789")
@pytest.mark.parametrize(
("given_dtype", "expected_dtype"),
[
("S", np.dtype("S5")),
("U", np.dtype("U5")),
],
)
def test_string_no_length_given(given_dtype, expected_dtype):
"""
给定的数据类型只有 'S' 或 'U' 而没有长度。在这些情况下,结果的长度由文件中找到的最长字符串决定。
"""
txt = StringIO("AAA,5-1\nBBBBB,0-3\nC,4-9\n")
res = np.loadtxt(txt, dtype=given_dtype, delimiter=",")
expected = np.array(
[['AAA', '5-1'], ['BBBBB', '0-3'], ['C', '4-9']], dtype=expected_dtype
)
assert_equal(res, expected)
assert_equal(res.dtype, expected_dtype)
def test_float_conversion():
"""
Some tests that the conversion to float64 works as accurately as the
Python built-in `float` function. In a naive version of the float parser,
these strings resulted in values that were off by an ULP or two.
"""
strings = [
'0.9999999999999999',
'9876543210.123456',
'5.43215432154321e+300',
'0.901',
'0.333',
]
txt = StringIO('\n'.join(strings))
res = np.loadtxt(txt)
expected = np.array([float(s) for s in strings])
assert_equal(res, expected)
def test_bool():
txt = StringIO("1, 0\n10, -1")
res = np.loadtxt(txt, dtype=bool, delimiter=",")
assert res.dtype == bool
assert_array_equal(res, [[True, False], [True, True]])
assert_array_equal(res.view(np.uint8), [[1, 0], [1, 1]])
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
@pytest.mark.parametrize("dtype", np.typecodes["AllInteger"])
@pytest.mark.filterwarnings("error:.*integer via a float.*:DeprecationWarning")
def test_integer_signs(dtype):
dtype = np.dtype(dtype)
assert np.loadtxt(["+2"], dtype=dtype) == 2
if dtype.kind == "u":
with pytest.raises(ValueError):
np.loadtxt(["-1\n"], dtype=dtype)
else:
assert np.loadtxt(["-2\n"], dtype=dtype) == -2
for sign in ["++", "+-", "--", "-+"]:
with pytest.raises(ValueError):
np.loadtxt([f"{sign}2\n"], dtype=dtype)
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
@pytest.mark.parametrize("dtype", np.typecodes["AllInteger"])
@pytest.mark.filterwarnings("error:.*integer via a float.*:DeprecationWarning")
def test_implicit_cast_float_to_int_fails(dtype):
txt = StringIO("1.0, 2.1, 3.7\n4, 5, 6")
with pytest.raises(ValueError):
np.loadtxt(txt, dtype=dtype, delimiter=",")
@pytest.mark.parametrize("dtype", (np.complex64, np.complex128))
@pytest.mark.parametrize("with_parens", (False, True))
def test_complex_parsing(dtype, with_parens):
s = "(1.0-2.5j),3.75,(7+-5.0j)\n(4),(-19e2j),(0)"
if not with_parens:
s = s.replace("(", "").replace(")", "")
res = np.loadtxt(StringIO(s), dtype=dtype, delimiter=",")
expected = np.array(
[[1.0-2.5j, 3.75, 7-5j], [4.0, -1900j, 0]], dtype=dtype
)
assert_equal(res, expected)
def test_read_from_generator():
def gen():
for i in range(4):
yield f"{i},{2*i},{i**2}"
res = np.loadtxt(gen(), dtype=int, delimiter=",")
expected = np.array([[0, 0, 0], [1, 2, 1], [2, 4, 4], [3, 6, 9]])
assert_equal(res, expected)
def test_read_from_generator_multitype():
def gen():
for i in range(3):
yield f"{i} {i / 4}"
res = np.loadtxt(gen(), dtype="i, d", delimiter=" ")
expected = np.array([(0, 0.0), (1, 0.25), (2, 0.5)], dtype="i, d")
assert_equal(res, expected)
def test_read_from_bad_generator():
def gen():
yield from ["1,2", b"3, 5", 12738]
with pytest.raises(
TypeError, match=r"non-string returned while reading data"):
np.loadtxt(gen(), dtype="i, i", delimiter=",")
@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
def test_object_cleanup_on_read_error():
sentinel = object()
already_read = 0
def conv(x):
nonlocal already_read
if already_read > 4999:
raise ValueError("failed half-way through!")
already_read += 1
return sentinel
txt = StringIO("x\n" * 10000)
with pytest.raises(ValueError, match="at row 5000, column 1"):
np.loadtxt(txt, dtype=object, converters={0: conv})
assert sys.getrefcount(sentinel) == 2
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
def test_character_not_bytes_compatible():
"""Test exception when a character cannot be encoded as 'S'."""
data = StringIO("–")
with pytest.raises(ValueError):
np.loadtxt(data, dtype="S5")
@pytest.mark.parametrize("conv", (0, [float], ""))
def test_invalid_converter(conv):
msg = (
"converters must be a dictionary mapping columns to converter "
"functions or a single callable."
)
with pytest.raises(TypeError, match=msg):
np.loadtxt(StringIO("1 2\n3 4"), converters=conv)
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
def test_converters_dict_raises_non_integer_key():
with pytest.raises(TypeError, match="keys of the converters dict"):
np.loadtxt(StringIO("1 2\n3 4"), converters={"a": int})
with pytest.raises(TypeError, match="keys of the converters dict"):
np.loadtxt(StringIO("1 2\n3 4"), converters={"a": int}, usecols=0)
@pytest.mark.parametrize("bad_col_ind", (3, -3))
def test_converters_dict_raises_non_col_key(bad_col_ind):
data = StringIO("1 2\n3 4")
with pytest.raises(ValueError, match="converter specified for column"):
np.loadtxt(data, converters={bad_col_ind: int})
def test_converters_dict_raises_val_not_callable():
with pytest.raises(TypeError,
match="values of the converters dictionary must be callable"):
np.loadtxt(StringIO("1 2\n3 4"), converters={0: 1})
@pytest.mark.parametrize("q", ('"', "'", "`"))
def test_quoted_field(q):
txt = StringIO(
f"{q}alpha, x{q}, 2.5\n{q}beta, y{q}, 4.5\n{q}gamma, z{q}, 5.0\n"
)
dtype = np.dtype([('f0', 'U8'), ('f1', np.float64)])
expected = np.array(
[("alpha, x", 2.5), ("beta, y", 4.5), ("gamma, z", 5.0)], dtype=dtype
)
res = np.loadtxt(txt, dtype=dtype, delimiter=",", quotechar=q)
assert_array_equal(res, expected)
@pytest.mark.parametrize("q", ('"', "'", "`"))
def test_quoted_field_with_whitepace_delimiter(q):
pass
txt = StringIO(
f"{q}alpha, x{q} 2.5\n{q}beta, y{q} 4.5\n{q}gamma, z{q} 5.0\n"
)
dtype = np.dtype([('f0', 'U8'), ('f1', np.float64)])
expected = np.array(
[("alpha, x", 2.5), ("beta, y", 4.5), ("gamma, z", 5.0)], dtype=dtype
)
res = np.loadtxt(txt, dtype=dtype, delimiter=None, quotechar=q)
assert_array_equal(res, expected)
def test_quoted_field_is_not_empty_nonstrict():
txt = StringIO('1\n\n"4"\n"')
expected = np.array(["1", "4", ""], dtype="U1")
res = np.loadtxt(txt, delimiter=",", dtype="U1", quotechar='"')
assert_equal(res, expected)
def test_consecutive_quotechar_escaped():
txt = StringIO('"Hello, my name is ""Monty""!"')
expected = np.array('Hello, my name is "Monty"!', dtype="U40")
res = np.loadtxt(txt, dtype="U40", delimiter=",", quotechar='"')
assert_equal(res, expected)
@pytest.mark.parametrize("data", ("", "\n\n\n", "# 1 2 3\n# 4 5 6\n"))
@pytest.mark.parametrize("ndmin", (0, 1, 2))
@pytest.mark.parametrize("usecols", [None, (1, 2, 3)])
def test_warn_on_no_data(data, ndmin, usecols):
"""检查当输入数据为空时是否发出 UserWarning。"""
if usecols is not None:
expected_shape = (0, 3)
elif ndmin == 2:
expected_shape = (0, 1)
else:
expected_shape = (0,)
txt = StringIO(data)
with pytest.warns(UserWarning, match="input contained no data"):
res = np.loadtxt(txt, ndmin=ndmin, usecols=usecols)
assert res.shape == expected_shape
with NamedTemporaryFile(mode="w") as fh:
fh.write(data)
fh.seek(0)
with pytest.warns(UserWarning, match="input contained no data"):
res = np.loadtxt(txt, ndmin=ndmin, usecols=usecols)
assert res.shape == expected_shape
@pytest.mark.parametrize("skiprows", (2, 3))
def test_warn_on_skipped_data(skiprows):
data = "1 2 3\n4 5 6"
txt = StringIO(data)
with pytest.warns(UserWarning, match="input contained no data"):
np.loadtxt(txt, skiprows=skiprows)
@pytest.mark.parametrize(["dtype", "value"], [
("i2", 0x0001), ("u2", 0x0001),
("i4", 0x00010203), ("u4", 0x00010203),
("i8", 0x0001020304050607), ("u8", 0x0001020304050607),
("float16", 3.07e-05),
("float32", 9.2557e-41), ("complex64", 9.2557e-41+2.8622554e-29j),
("float64", -1.758571353180402e-24),
("complex128", repr(5.406409232372729e-29-1.758571353180402e-24j)),
("longdouble", 0x01020304050607),
("clongdouble", repr(0x01020304050607 + (0x00121314151617 * 1j))),
("U2", "\U00010203\U000a0b0c")])
@pytest.mark.parametrize("swap", [True, False])
def test_byteswapping_and_unaligned(dtype, value, swap):
dtype = np.dtype(dtype)
data = [f"x,{value}\n"]
if swap:
dtype = dtype.newbyteorder()
full_dt = np.dtype([("a", "S1"), ("b", dtype)], align=False)
assert full_dt.fields["b"][1] == 1
res = np.loadtxt(data, dtype=full_dt, delimiter=",", max_rows=1)
assert res["b"] == dtype.type(value)
@pytest.mark.parametrize("dtype",
np.typecodes["AllInteger"] + "efdFD" + "?")
def test_unicode_whitespace_stripping(dtype):
txt = StringIO(' 3 ,"\u202F2\n"')
res = np.loadtxt(txt, dtype=dtype, delimiter=",", quotechar='"')
assert_array_equal(res, np.array([3, 2]).astype(dtype))
@pytest.mark.parametrize("dtype", "FD")
def test_unicode_whitespace_stripping_complex(dtype):
line = " 1 , 2+3j , ( 4+5j ), ( 6+-7j ) , 8j , ( 9j ) \n"
data = [line, line.replace(" ", "\u202F")]
res = np.loadtxt(data, dtype=dtype, delimiter=',')
assert_array_equal(res, np.array([[1, 2+3j, 4+5j, 6-7j, 8j, 9j]] * 2))
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
@pytest.mark.parametrize("dtype", "FD")
@pytest.mark.parametrize("field",
["1 +2j", "1+ 2j", "1+2 j", "1+-+3", "(1j", "(1", "(1+2j", "1+2j)"])
def test_bad_complex(dtype, field):
with pytest.raises(ValueError):
np.loadtxt([field + "\n"], dtype=dtype, delimiter=",")
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
@pytest.mark.parametrize("dtype",
np.typecodes["AllInteger"] + "efgdFDG" + "?")
def test_nul_character_error(dtype):
if dtype.lower() == "g":
pytest.xfail("longdouble/clongdouble assignment may misbehave.")
with pytest.raises(ValueError):
np.loadtxt(["1\000"], dtype=dtype, delimiter=",", quotechar='"')
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
@pytest.mark.parametrize("dtype",
np.typecodes["AllInteger"] + "efgdFDG" + "?")
def test_no_thousands_support(dtype):
if dtype == "e":
pytest.skip("half assignment currently uses Python float converter")
if dtype in "eG":
pytest.xfail("clongdouble assignment is buggy (uses `complex`?).")
assert int("1_1") == float("1_1") == complex("1_1") == 11
with pytest.raises(ValueError):
np.loadtxt(["1_1\n"], dtype=dtype)
@pytest.mark.parametrize("data", [
["1,2\n", "2\n,3\n"],
["1,2\n", "2\r,3\n"]])
def test_bad_newline_in_iterator(data):
msg = "Found an unquoted embedded newline within a single line"
with pytest.raises(ValueError, match=msg):
np.loadtxt(data, delimiter=",")
@pytest.mark.parametrize("data", [
["1,2\n", "2,3\r\n"],
["1,2\n", "'2\n',3\n"],
["1,2\n", "'2\r',3\n"],
["1,2\n", "'2\r\n',3\n"],
])
def test_good_newline_in_iterator(data):
res = np.loadtxt(data, delimiter=",", quotechar="'")
assert_array_equal(res, [[1., 2.], [2., 3.]])
@pytest.mark.parametrize("newline", ["\n", "\r", "\r\n"])
def test_universal_newlines_quoted(newline):
data = ['1,"2\n"\n', '3,"4\n', '1"\n']
data = [row.replace("\n", newline) for row in data]
res = np.loadtxt(data, dtype=object, delimiter=",", quotechar='"')
assert_array_equal(res, [['1', f'2{newline}'], ['3', f'4{newline}1']])
def test_null_character():
res = np.loadtxt(["1\0002\0003\n", "4\0005\0006"], delimiter="\000")
assert_array_equal(res, [[1, 2, 3], [4, 5, 6]])
res = np.loadtxt(["1\000,2\000,3\n", "4\000,5\000,6"],
delimiter=",", dtype=object)
assert res.tolist() == [["1\000", "2\000", "3"], ["4\000", "5\000", "6"]]
def test_iterator_fails_getting_next_line():
class BadSequence:
def __len__(self):
return 100
def __getitem__(self, item):
if item == 50:
raise RuntimeError("Bad things happened!")
return f"{item}, {item+1}"
with pytest.raises(RuntimeError, match="Bad things happened!"):
np.loadtxt(BadSequence(), dtype=int, delimiter=",")
class TestCReaderUnitTests:
def test_not_an_filelike(self):
with pytest.raises(AttributeError, match=".*read"):
np._core._multiarray_umath._load_from_filelike(
object(), dtype=np.dtype("i"), filelike=True)
def test_filelike_read_fails(self):
class BadFileLike:
counter = 0
def read(self, size):
self.counter += 1
if self.counter > 20:
raise RuntimeError("Bad bad bad!")
return "1,2,3\n"
with pytest.raises(RuntimeError, match="Bad bad bad!"):
np._core._multiarray_umath._load_from_filelike(
BadFileLike(), dtype=np.dtype("i"), filelike=True)
def test_filelike_bad_read(self):
class BadFileLike:
counter = 0
def read(self, size):
return 1234
with pytest.raises(TypeError,
match="non-string returned while reading data"):
np._core._multiarray_umath._load_from_filelike(
BadFileLike(), dtype=np.dtype("i"), filelike=True)
def test_not_an_iter(self):
with pytest.raises(TypeError,
match="error reading from object, expected an iterable"):
np._core._multiarray_umath._load_from_filelike(
object(), dtype=np.dtype("i"), filelike=False)
def test_bad_type(self):
with pytest.raises(TypeError, match="internal error: dtype must"):
np._core._multiarray_umath._load_from_filelike(
object(), dtype="i", filelike=False)
def test_bad_encoding(self):
with pytest.raises(TypeError, match="encoding must be a unicode"):
np._core._multiarray_umath._load_from_filelike(
object(), dtype=np.dtype("i"), filelike=False, encoding=123)
@pytest.mark.parametrize("newline", ["\r", "\n", "\r\n"])
def test_manual_universal_newlines(self, newline):
data = StringIO('0\n1\n"2\n"\n3\n4 #\n'.replace("\n", newline),
newline="")
res = np._core._multiarray_umath._load_from_filelike(
data, dtype=np.dtype("U10"), filelike=True,
quote='"', comment="#", skiplines=1)
assert_array_equal(res[:, 0], ["1", f"2{newline}", "3", "4 "])
def test_delimiter_comment_collision_raises():
with pytest.raises(TypeError, match=".*control characters.*incompatible"):
np.loadtxt(StringIO("1, 2, 3"), delimiter=",", comments=",")
def test_delimiter_quotechar_collision_raises():
with pytest.raises(TypeError, match=".*control characters.*incompatible"):
np.loadtxt(StringIO("1, 2, 3"), delimiter=",", quotechar=",")
def test_comment_quotechar_collision_raises():
with pytest.raises(TypeError, match=".*control characters.*incompatible"):
np.loadtxt(StringIO("1 2 3"), comments="#", quotechar="#")
def test_delimiter_and_multiple_comments_collision_raises():
with pytest.raises(
TypeError, match="Comment characters.*cannot include the delimiter"
):
np.loadtxt(StringIO("1, 2, 3"), delimiter=",", comments=["#", ","])
@pytest.mark.parametrize(
"ws",
(
" ",
"\t",
"\u2003",
"\u00A0",
"\u3000",
)
)
def test_collision_with_default_delimiter_raises(ws):
with pytest.raises(TypeError, match=".*control characters.*incompatible"):
np.loadtxt(StringIO(f"1{ws}2{ws}3\n4{ws}5{ws}6\n"), comments=ws)
with pytest.raises(TypeError, match=".*control characters.*incompatible"):
np.loadtxt(StringIO(f"1{ws}2{ws}3\n4{ws}5{ws}6\n"), quotechar=ws)
@pytest.mark.parametrize("nl", ("\n", "\r"))
def test_control_character_newline_raises(nl):
txt = StringIO(f"1{nl}2{nl}3{nl}{nl}4{nl}5{nl}6{nl}{nl}")
msg = "control character.*cannot be a newline"
with pytest.raises(TypeError, match=msg):
np.loadtxt(txt, delimiter=nl)
with pytest.raises(TypeError, match=msg):
np.loadtxt(txt, comments=nl)
with pytest.raises(TypeError, match=msg):
np.loadtxt(txt, quotechar=nl)
@pytest.mark.parametrize(
("generic_data", "long_datum", "unitless_dtype", "expected_dtype"),
[
("2012-03", "2013-01-15", "M8", "M8[D]"),
("spam-a-lot", "tis_but_a_scratch", "U", "U17"),
],
)
@pytest.mark.parametrize("nrows", (10, 50000, 60000))
def test_parametric_unit_discovery(
generic_data, long_datum, unitless_dtype, expected_dtype, nrows
):
"""检查当用户指定无单位的日期时间时,从数据中正确识别单位(例如月、日、秒)。"""
data = [generic_data] * 50000 + [long_datum]
expected = np.array(data, dtype=expected_dtype)
txt = StringIO("\n".join(data))
a = np.loadtxt(txt, dtype=unitless_dtype)
assert a.dtype == expected.dtype
assert_equal(a, expected)
fd, fname = mkstemp()
os.close(fd)
with open(fname, "w") as fh:
fh.write("\n".join(data))
a = np.loadtxt(fname, dtype=unitless_dtype)
os.remove(fname)
assert a.dtype == expected.dtype
assert_equal(a, expected)
def test_str_dtype_unit_discovery_with_converter():
data = ["spam-a-lot"] * 60000 + ["XXXtis_but_a_scratch"]
expected = np.array(["spam-a-lot"] * 60000 + ["tis_but_a_scratch"], dtype="U17")
conv = lambda s: s.strip("XXX")
txt = StringIO("\n".join(data))
a = np.loadtxt(txt, dtype="U", converters=conv)
assert a.dtype == expected.dtype
assert_equal(a, expected)
fd, fname = mkstemp()
os.close(fd)
with open(fname, "w") as fh:
fh.write("\n".join(data))
a = np.loadtxt(fname, dtype="U", converters=conv)
os.remove(fname)
assert a.dtype == expected.dtype
assert_equal(a, expected)
@pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
reason="PyPy bug in error formatting")
def test_control_character_empty():
with pytest.raises(TypeError, match="Text reading control character must"):
np.loadtxt(StringIO("1 2 3"), delimiter="")
with pytest.raises(TypeError, match="Text reading control character must"):
np.loadtxt(StringIO("1 2 3"), quotechar="")
with pytest.raises(ValueError, match="comments cannot be an empty string"):
np.loadtxt(StringIO("1 2 3"), comments="")
with pytest.raises(ValueError, match="comments cannot be an empty string"):
np.loadtxt(StringIO("1 2 3"), comments=["#", ""])
def test_control_characters_as_bytes():
"""Byte control characters (comments, delimiter) are supported."""
a = np.loadtxt(StringIO("#header\n1,2,3"), comments=b"#", delimiter=b",")
assert_equal(a, [1, 2, 3])
@pytest.mark.filterwarnings('ignore::UserWarning')
def test_field_growing_cases():
res = np.loadtxt([""], delimiter=",", dtype=bytes)
assert len(res) == 0
for i in range(1, 1024):
res = np.loadtxt(["," * i], delimiter=",", dtype=bytes)
assert len(res) == i+1
.\numpy\numpy\lib\tests\test_mixins.py
import numbers
import operator
import numpy as np
from numpy.testing import assert_, assert_equal, assert_raises
class ArrayLike(np.lib.mixins.NDArrayOperatorsMixin):
def __init__(self, value):
self.value = np.asarray(value)
_HANDLED_TYPES = (np.ndarray, numbers.Number)
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
out = kwargs.get('out', ())
for x in inputs + out:
if not isinstance(x, self._HANDLED_TYPES + (ArrayLike,)):
return NotImplemented
inputs = tuple(x.value if isinstance(x, ArrayLike) else x
for x in inputs)
if out:
kwargs['out'] = tuple(
x.value if isinstance(x, ArrayLike) else x
for x in out)
result = getattr(ufunc, method)(*inputs, **kwargs)
if type(result) is tuple:
return tuple(type(self)(x) for x in result)
elif method == 'at':
return None
else:
return type(self)(result)
def __repr__(self):
return '%s(%r)' % (type(self).__name__, self.value)
def wrap_array_like(result):
if type(result) is tuple:
return tuple(ArrayLike(r) for r in result)
else:
return ArrayLike(result)
def _assert_equal_type_and_value(result, expected, err_msg=None):
assert_equal(type(result), type(expected), err_msg=err_msg)
if isinstance(result, tuple):
assert_equal(len(result), len(expected), err_msg=err_msg)
for result_item, expected_item in zip(result, expected):
_assert_equal_type_and_value(result_item, expected_item, err_msg)
else:
assert_equal(result.value, expected.value, err_msg=err_msg)
assert_equal(getattr(result.value, 'dtype', None),
getattr(expected.value, 'dtype', None), err_msg=err_msg)
_ALL_BINARY_OPERATORS = [
operator.lt,
operator.le,
operator.eq,
operator.ne,
operator.gt,
operator.ge,
operator.add,
operator.sub,
operator.mul,
operator.truediv,
operator.floordiv,
operator.mod,
divmod,
pow,
operator.lshift,
operator.rshift,
operator.and_,
operator.xor,
operator.or_,
]
class TestNDArrayOperatorsMixin:
def test_array_like_add(self):
def check(result):
_assert_equal_type_and_value(result, ArrayLike(0))
check(ArrayLike(0) + 0)
check(0 + ArrayLike(0))
check(ArrayLike(0) + np.array(0))
check(np.array(0) + ArrayLike(0))
check(ArrayLike(np.array(0)) + 0)
check(0 + ArrayLike(np.array(0)))
check(ArrayLike(np.array(0)) + np.array(0))
check(np.array(0) + ArrayLike(np.array(0)))
def test_inplace(self):
array_like = ArrayLike(np.array([0]))
array_like += 1
_assert_equal_type_and_value(array_like, ArrayLike(np.array([1])))
array = np.array([0])
array += ArrayLike(1)
_assert_equal_type_and_value(array, ArrayLike(np.array([1])))
def test_opt_out(self):
class OptOut:
"""Object that opts out of __array_ufunc__."""
__array_ufunc__ = None
def __add__(self, other):
return self
def __radd__(self, other):
return self
array_like = ArrayLike(1)
opt_out = OptOut()
assert_(array_like + opt_out is opt_out)
assert_(opt_out + array_like is opt_out)
with assert_raises(TypeError):
array_like += opt_out
with assert_raises(TypeError):
array_like - opt_out
with assert_raises(TypeError):
opt_out - array_like
def test_subclass(self):
class SubArrayLike(ArrayLike):
"""Should take precedence over ArrayLike."""
x = ArrayLike(0)
y = SubArrayLike(1)
_assert_equal_type_and_value(x + y, y)
_assert_equal_type_and_value(y + x, y)
def test_object(self):
x = ArrayLike(0)
obj = object()
with assert_raises(TypeError):
x + obj
with assert_raises(TypeError):
obj + x
with assert_raises(TypeError):
x += obj
def test_unary_methods(self):
array = np.array([-1, 0, 1, 2])
array_like = ArrayLike(array)
for op in [operator.neg,
operator.pos,
abs,
operator.invert]:
_assert_equal_type_and_value(op(array_like), ArrayLike(op(array)))
def test_forward_binary_methods(self):
array = np.array([-1, 0, 1, 2])
array_like = ArrayLike(array)
for op in _ALL_BINARY_OPERATORS:
expected = wrap_array_like(op(array, 1))
actual = op(array_like, 1)
err_msg = 'failed for operator {}'.format(op)
_assert_equal_type_and_value(expected, actual, err_msg=err_msg)
def test_reflected_binary_methods(self):
for op in _ALL_BINARY_OPERATORS:
expected = wrap_array_like(op(2, 1))
actual = op(2, ArrayLike(1))
err_msg = 'failed for operator {}'.format(op)
_assert_equal_type_and_value(expected, actual, err_msg=err_msg)
def test_matmul(self):
array = np.array([1, 2], dtype=np.float64)
array_like = ArrayLike(array)
expected = ArrayLike(np.float64(5))
_assert_equal_type_and_value(expected, np.matmul(array_like, array))
_assert_equal_type_and_value(
expected, operator.matmul(array_like, array))
_assert_equal_type_and_value(
expected, operator.matmul(array, array_like))
def test_ufunc_at(self):
array = ArrayLike(np.array([1, 2, 3, 4]))
assert_(np.negative.at(array, np.array([0, 1])) is None)
_assert_equal_type_and_value(array, ArrayLike([-1, -2, 3, 4]))
def test_ufunc_two_outputs(self):
mantissa, exponent = np.frexp(2 ** -3)
expected = (ArrayLike(mantissa), ArrayLike(exponent))
_assert_equal_type_and_value(
np.frexp(ArrayLike(2 ** -3)), expected)
_assert_equal_type_and_value(
np.frexp(ArrayLike(np.array(2 ** -3))), expected)
.\numpy\numpy\lib\tests\test_nanfunctions.py
import warnings
import pytest
import inspect
from functools import partial
import numpy as np
from numpy._core.numeric import normalize_axis_tuple
from numpy.exceptions import AxisError, ComplexWarning
from numpy.lib._nanfunctions_impl import _nan_mask, _replace_nan
from numpy.testing import (
assert_, assert_equal, assert_almost_equal, assert_raises,
assert_raises_regex, assert_array_equal, suppress_warnings
)
_ndat = np.array([[0.6244, np.nan, 0.2692, 0.0116, np.nan, 0.1170],
[0.5351, -0.9403, np.nan, 0.2100, 0.4759, 0.2833],
[np.nan, np.nan, np.nan, 0.1042, np.nan, -0.5954],
[0.1610, np.nan, np.nan, 0.1859, 0.3146, np.nan]])
_rdat = [np.array([0.6244, 0.2692, 0.0116, 0.1170]),
np.array([0.5351, -0.9403, 0.2100, 0.4759, 0.2833]),
np.array([0.1042, -0.5954]),
np.array([0.1610, 0.1859, 0.3146])]
_ndat_ones = np.array([[0.6244, 1.0, 0.2692, 0.0116, 1.0, 0.1170],
[0.5351, -0.9403, 1.0, 0.2100, 0.4759, 0.2833],
[1.0, 1.0, 1.0, 0.1042, 1.0, -0.5954],
[0.1610, 1.0, 1.0, 0.1859, 0.3146, 1.0]])
_ndat_zeros = np.array([[0.6244, 0.0, 0.2692, 0.0116, 0.0, 0.1170],
[0.5351, -0.9403, 0.0, 0.2100, 0.4759, 0.2833],
[0.0, 0.0, 0.0, 0.1042, 0.0, -0.5954],
[0.1610, 0.0, 0.0, 0.1859, 0.3146, 0.0]])
class TestSignatureMatch:
NANFUNCS = {
np.nanmin: np.amin,
np.nanmax: np.amax,
np.nanargmin: np.argmin,
np.nanargmax: np.argmax,
np.nansum: np.sum,
np.nanprod: np.prod,
np.nancumsum: np.cumsum,
np.nancumprod: np.cumprod,
np.nanmean: np.mean,
np.nanmedian: np.median,
np.nanpercentile: np.percentile,
np.nanquantile: np.quantile,
np.nanvar: np.var,
np.nanstd: np.std,
}
IDS = [k.__name__ for k in NANFUNCS]
@staticmethod
def get_signature(func, default="..."):
"""构造函数签名并替换所有默认参数值。"""
prm_list = []
signature = inspect.signature(func)
for prm in signature.parameters.values():
if prm.default is inspect.Parameter.empty:
prm_list.append(prm)
else:
prm_list.append(prm.replace(default=default))
return inspect.Signature(prm_list)
@pytest.mark.parametrize("nan_func,func", NANFUNCS.items(), ids=IDS)
def test_signature_match(self, nan_func, func):
signature = self.get_signature(func)
nan_signature = self.get_signature(nan_func)
np.testing.assert_equal(signature, nan_signature)
def test_exhaustiveness(self):
"""Validate that all nan functions are actually tested."""
np.testing.assert_equal(
set(self.IDS), set(np.lib._nanfunctions_impl.__all__)
)
class TestNanFunctions_MinMax:
nanfuncs = [np.nanmin, np.nanmax]
stdfuncs = [np.min, np.max]
def test_mutation(self):
ndat = _ndat.copy()
for f in self.nanfuncs:
f(ndat)
assert_equal(ndat, _ndat)
def test_keepdims(self):
mat = np.eye(3)
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
for axis in [None, 0, 1]:
tgt = rf(mat, axis=axis, keepdims=True)
res = nf(mat, axis=axis, keepdims=True)
assert_(res.ndim == tgt.ndim)
def test_out(self):
mat = np.eye(3)
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
resout = np.zeros(3)
tgt = rf(mat, axis=1)
res = nf(mat, axis=1, out=resout)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
def test_dtype_from_input(self):
codes = 'efdgFDG'
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
for c in codes:
mat = np.eye(3, dtype=c)
tgt = rf(mat, axis=1).dtype.type
res = nf(mat, axis=1).dtype.type
assert_(res is tgt)
tgt = rf(mat, axis=None).dtype.type
res = nf(mat, axis=None).dtype.type
assert_(res is tgt)
def test_result_values(self):
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
tgt = [rf(d) for d in _rdat]
res = nf(_ndat, axis=1)
assert_almost_equal(res, tgt)
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan),
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
match = "All-NaN slice encountered"
for func in self.nanfuncs:
with pytest.warns(RuntimeWarning, match=match):
out = func(array, axis=axis)
assert np.isnan(out).all()
assert out.dtype == array.dtype
def test_masked(self):
mat = np.ma.fix_invalid(_ndat)
msk = mat._mask.copy()
for f in [np.nanmin]:
res = f(mat, axis=1)
tgt = f(_ndat, axis=1)
assert_equal(res, tgt)
assert_equal(mat._mask, msk)
assert_(not np.isinf(mat).any())
def test_scalar(self):
for f in self.nanfuncs:
assert_(f(0.) == 0.)
def test_subclass(self):
class MyNDArray(np.ndarray):
pass
mine = np.eye(3).view(MyNDArray)
for f in self.nanfuncs:
res = f(mine, axis=0)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == (3,))
res = f(mine, axis=1)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == (3,))
res = f(mine)
assert_(res.shape == ())
mine[1] = np.nan
for f in self.nanfuncs:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
res = f(mine, axis=0)
assert_(isinstance(res, MyNDArray))
assert_(not np.any(np.isnan(res)))
assert_(len(w) == 0)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
res = f(mine, axis=1)
assert_(isinstance(res, MyNDArray))
assert_(np.isnan(res[1]) and not np.isnan(res[0])
and not np.isnan(res[2]))
assert_(len(w) == 1, 'no warning raised')
assert_(issubclass(w[0].category, RuntimeWarning))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
res = f(mine)
assert_(res.shape == ())
assert_(res != np.nan)
assert_(len(w) == 0)
def test_object_array(self):
arr = np.array([[1.0, 2.0], [np.nan, 4.0], [np.nan, np.nan]], dtype=object)
assert_equal(np.nanmin(arr), 1.0)
assert_equal(np.nanmin(arr, axis=0), [1.0, 2.0])
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_equal(list(np.nanmin(arr, axis=1)), [1.0, 4.0, np.nan])
assert_(len(w) == 1, 'no warning raised')
assert_(issubclass(w[0].category, RuntimeWarning))
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
def test_initial(self, dtype):
class MyNDArray(np.ndarray):
pass
ar = np.arange(9).astype(dtype)
ar[:5] = np.nan
for f in self.nanfuncs:
initial = 100 if f is np.nanmax else 0
ret1 = f(ar, initial=initial)
assert ret1.dtype == dtype
assert ret1 == initial
ret2 = f(ar.view(MyNDArray), initial=initial)
assert ret2.dtype == dtype
assert ret2 == initial
def test_where(self, dtype):
class MyNDArray(np.ndarray):
pass
ar = np.arange(9).reshape(3, 3).astype(dtype)
ar[0, :] = np.nan
where = np.ones_like(ar, dtype=np.bool)
where[:, 0] = False
for f in self.nanfuncs:
reference = 4 if f is np.nanmin else 8
ret1 = f(ar, where=where, initial=5)
assert ret1.dtype == dtype
assert ret1 == reference
ret2 = f(ar.view(MyNDArray), where=where, initial=5)
assert ret2.dtype == dtype
assert ret2 == reference
class TestNanFunctions_ArgminArgmax:
nanfuncs = [np.nanargmin, np.nanargmax]
def test_mutation(self):
ndat = _ndat.copy()
for f in self.nanfuncs:
f(ndat)
assert_equal(ndat, _ndat)
def test_result_values(self):
for f, fcmp in zip(self.nanfuncs, [np.greater, np.less]):
for row in _ndat:
with suppress_warnings() as sup:
sup.filter(RuntimeWarning, "invalid value encountered in")
ind = f(row)
val = row[ind]
assert_(not np.isnan(val))
assert_(not fcmp(val, row).any())
assert_(not np.equal(val, row[:ind]).any())
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan),
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
for func in self.nanfuncs:
with pytest.raises(ValueError, match="All-NaN slice encountered"):
func(array, axis=axis)
def test_empty(self):
mat = np.zeros((0, 3))
for f in self.nanfuncs:
for axis in [0, None]:
assert_raises_regex(
ValueError,
"attempt to get argm.. of an empty sequence",
f, mat, axis=axis)
for axis in [1]:
res = f(mat, axis=axis)
assert_equal(res, np.zeros(0))
def test_scalar(self):
for f in self.nanfuncs:
assert_(f(0.) == 0.)
def test_subclass(self):
class MyNDArray(np.ndarray):
pass
mine = np.eye(3).view(MyNDArray)
for f in self.nanfuncs:
res = f(mine, axis=0)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == (3,))
res = f(mine, axis=1)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == (3,))
res = f(mine)
assert_(res.shape == ())
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
def test_keepdims(self, dtype):
ar = np.arange(9).astype(dtype)
ar[:5] = np.nan
for f in self.nanfuncs:
reference = 5 if f is np.nanargmin else 8
ret = f(ar, keepdims=True)
assert ret.ndim == ar.ndim
assert ret == reference
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
def test_out(self, dtype):
ar = np.arange(9).astype(dtype)
ar[:5] = np.nan
for f in self.nanfuncs:
out = np.zeros((), dtype=np.intp)
reference = 5 if f is np.nanargmin else 8
ret = f(ar, out=out)
assert ret is out
assert ret == reference
_TEST_ARRAYS = {
"0d": np.array(5),
"1d": np.array([127, 39, 93, 87, 46])
}
for _v in _TEST_ARRAYS.values():
_v.setflags(write=False)
@pytest.mark.parametrize(
"dtype",
np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O",
)
@pytest.mark.parametrize(
"mat", _TEST_ARRAYS.values(),
ids=_TEST_ARRAYS.keys()
)
class TestNanFunctions_NumberTypes:
nanfuncs = {
np.nanmin: np.min,
np.nanmax: np.max,
np.nanargmin: np.argmin,
np.nanargmax: np.argmax,
np.nansum: np.sum,
np.nanprod: np.prod,
np.nancumsum: np.cumsum,
np.nancumprod: np.cumprod,
np.nanmean: np.mean,
np.nanmedian: np.median,
np.nanvar: np.var,
np.nanstd: np.std
}
nanfunc_ids = [i.__name__ for i in nanfuncs]
@pytest.mark.parametrize("nanfunc,func", nanfuncs.items(), ids=nanfunc_ids)
@np.errstate(over="ignore")
def test_nanfunc(self, mat, dtype, nanfunc, func):
mat = mat.astype(dtype)
tgt = func(mat)
out = nanfunc(mat)
assert_almost_equal(out, tgt)
if dtype == "O":
assert type(out) is type(tgt)
else:
assert out.dtype == tgt.dtype
@pytest.mark.parametrize(
"nanfunc,func",
[(np.nanquantile, np.quantile), (np.nanpercentile, np.percentile)],
ids=["nanquantile", "nanpercentile"],
)
def test_nanfunc_q(self, mat, dtype, nanfunc, func):
mat = mat.astype(dtype)
if mat.dtype.kind == "c":
assert_raises(TypeError, func, mat, q=1)
assert_raises(TypeError, nanfunc, mat, q=1)
else:
tgt = func(mat, q=1)
out = nanfunc(mat, q=1)
assert_almost_equal(out, tgt)
if dtype == "O":
assert type(out) is type(tgt)
else:
assert out.dtype == tgt.dtype
@pytest.mark.parametrize(
"nanfunc,func",
[(np.nanvar, np.var), (np.nanstd, np.std)],
ids=["nanvar", "nanstd"],
)
def test_nanfunc_ddof(self, mat, dtype, nanfunc, func):
mat = mat.astype(dtype)
tgt = func(mat, ddof=0.5)
out = nanfunc(mat, ddof=0.5)
assert_almost_equal(out, tgt)
if dtype == "O":
assert type(out) is type(tgt)
else:
assert out.dtype == tgt.dtype
@pytest.mark.parametrize(
"nanfunc", [np.nanvar, np.nanstd]
)
def test_nanfunc_correction(self, mat, dtype, nanfunc):
mat = mat.astype(dtype)
assert_almost_equal(
nanfunc(mat, correction=0.5),
nanfunc(mat, ddof=0.5)
)
err_msg = "ddof and correction can't be provided simultaneously."
with assert_raises_regex(ValueError, err_msg):
nanfunc(mat, ddof=0.5, correction=0.5)
with assert_raises_regex(ValueError, err_msg):
nanfunc(mat, ddof=1, correction=0)
def test_mutation(self):
ndat = _ndat.copy()
for f in self.nanfuncs:
f(ndat)
assert_equal(ndat, _ndat)
def test_keepdims(self):
mat = np.eye(3)
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
for axis in [None, 0, 1]:
tgt = rf(mat, axis=axis, keepdims=True)
res = nf(mat, axis=axis, keepdims=True)
assert_(res.ndim == tgt.ndim)
def test_out(self):
mat = np.eye(3)
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
resout = np.zeros(3)
tgt = rf(mat, axis=1)
res = nf(mat, axis=1, out=resout)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
def test_dtype_from_dtype(self):
mat = np.eye(3)
codes = 'efdgFDG'
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
for c in codes:
with suppress_warnings() as sup:
if nf in {np.nanstd, np.nanvar} and c in 'FDG':
sup.filter(ComplexWarning)
tgt = rf(mat, dtype=np.dtype(c), axis=1).dtype.type
res = nf(mat, dtype=np.dtype(c), axis=1).dtype.type
assert_(res is tgt)
tgt = rf(mat, dtype=np.dtype(c), axis=None).dtype.type
res = nf(mat, dtype=np.dtype(c), axis=None).dtype.type
assert_(res is tgt)
def test_dtype_from_char(self):
mat = np.eye(3)
codes = 'efdgFDG'
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
for c in codes:
with suppress_warnings() as sup:
if nf in {np.nanstd, np.nanvar} and c in 'FDG':
sup.filter(ComplexWarning)
tgt = rf(mat, dtype=c, axis=1).dtype.type
res = nf(mat, dtype=c, axis=1).dtype.type
assert_(res is tgt)
tgt = rf(mat, dtype=c, axis=None).dtype.type
res = nf(mat, dtype=c, axis=None).dtype.type
assert_(res is tgt)
def test_dtype_from_input(self):
codes = 'efdgFDG'
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
for c in codes:
mat = np.eye(3, dtype=c)
tgt = rf(mat, axis=1).dtype.type
res = nf(mat, axis=1).dtype.type
assert_(res is tgt, "res %s, tgt %s" % (res, tgt))
tgt = rf(mat, axis=None).dtype.type
res = nf(mat, axis=None).dtype.type
assert_(res is tgt)
def test_result_values(self):
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
tgt = [rf(d) for d in _rdat]
res = nf(_ndat, axis=1)
assert_almost_equal(res, tgt)
def test_scalar(self):
for f in self.nanfuncs:
assert_(f(0.) == 0.)
def test_subclass(self):
class MyNDArray(np.ndarray):
pass
array = np.eye(3)
mine = array.view(MyNDArray)
for f in self.nanfuncs:
expected_shape = f(array, axis=0).shape
res = f(mine, axis=0)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == expected_shape)
expected_shape = f(array, axis=1).shape
res = f(mine, axis=1)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == expected_shape)
expected_shape = f(array).shape
res = f(mine)
assert_(isinstance(res, MyNDArray))
assert_(res.shape == expected_shape)
class TestNanFunctions_SumProd(SharedNanFunctionsTestsMixin):
nanfuncs = [np.nansum, np.nanprod]
stdfuncs = [np.sum, np.prod]
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan),
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
for func, identity in zip(self.nanfuncs, [0, 1]):
out = func(array, axis=axis)
assert np.all(out == identity)
assert out.dtype == array.dtype
def test_empty(self):
for f, tgt_value in zip([np.nansum, np.nanprod], [0, 1]):
mat = np.zeros((0, 3))
tgt = [tgt_value]*3
res = f(mat, axis=0)
assert_equal(res, tgt)
tgt = []
res = f(mat, axis=1)
assert_equal(res, tgt)
tgt = tgt_value
res = f(mat, axis=None)
assert_equal(res, tgt)
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
def test_initial(self, dtype):
ar = np.arange(9).astype(dtype)
ar[:5] = np.nan
for f in self.nanfuncs:
reference = 28 if f is np.nansum else 3360
ret = f(ar, initial=2)
assert ret.dtype == dtype
assert ret == reference
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
def test_where(self, dtype):
ar = np.arange(9).reshape(3, 3).astype(dtype)
ar[0, :] = np.nan
where = np.ones_like(ar, dtype=np.bool)
where[:, 0] = False
for f in self.nanfuncs:
reference = 26 if f is np.nansum else 2240
ret = f(ar, where=where, initial=2)
assert ret.dtype == dtype
assert ret == reference
class TestNanFunctions_CumSumProd(SharedNanFunctionsTestsMixin):
nanfuncs = [np.nancumsum, np.nancumprod]
stdfuncs = [np.cumsum, np.cumprod]
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan)
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
for func, identity in zip(self.nanfuncs, [0, 1]):
out = func(array)
assert np.all(out == identity)
assert out.dtype == array.dtype
def test_empty(self):
for f, tgt_value in zip(self.nanfuncs, [0, 1]):
mat = np.zeros((0, 3))
tgt = tgt_value * np.ones((0, 3))
res = f(mat, axis=0)
assert_equal(res, tgt)
tgt = mat
res = f(mat, axis=1)
assert_equal(res, tgt)
tgt = np.zeros((0))
res = f(mat, axis=None)
assert_equal(res, tgt)
def test_keepdims(self):
for f, g in zip(self.nanfuncs, self.stdfuncs):
mat = np.eye(3)
for axis in [None, 0, 1]:
tgt = f(mat, axis=axis, out=None)
res = g(mat, axis=axis, out=None)
assert_(res.ndim == tgt.ndim)
for f in self.nanfuncs:
d = np.ones((3, 5, 7, 11))
rs = np.random.RandomState(0)
d[rs.rand(*d.shape) < 0.5] = np.nan
res = f(d, axis=None)
assert_equal(res.shape, (1155,))
for axis in np.arange(4):
res = f(d, axis=axis)
assert_equal(res.shape, (3, 5, 7, 11))
def test_result_values(self):
for axis in (-2, -1, 0, 1, None):
tgt = np.cumprod(_ndat_ones, axis=axis)
res = np.nancumprod(_ndat, axis=axis)
assert_almost_equal(res, tgt)
tgt = np.cumsum(_ndat_zeros, axis=axis)
res = np.nancumsum(_ndat, axis=axis)
assert_almost_equal(res, tgt)
def test_out(self):
mat = np.eye(3)
for nf, rf in zip(self.nanfuncs, self.stdfuncs):
resout = np.eye(3)
for axis in (-2, -1, 0, 1):
tgt = rf(mat, axis=axis)
res = nf(mat, axis=axis, out=resout)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
class TestNanFunctions_MeanVarStd(SharedNanFunctionsTestsMixin):
nanfuncs = [np.nanmean, np.nanvar, np.nanstd]
stdfuncs = [np.mean, np.var, np.std]
def test_dtype_error(self):
for f in self.nanfuncs:
for dtype in [np.bool, np.int_, np.object_]:
assert_raises(TypeError, f, _ndat, axis=1, dtype=dtype)
def test_out_dtype_error(self):
for f in self.nanfuncs:
for dtype in [np.bool, np.int_, np.object_]:
out = np.empty(_ndat.shape[0], dtype=dtype)
assert_raises(TypeError, f, _ndat, axis=1, out=out)
def test_ddof(self):
nanfuncs = [np.nanvar, np.nanstd]
stdfuncs = [np.var, np.std]
for nf, rf in zip(nanfuncs, stdfuncs):
for ddof in [0, 1]:
tgt = [rf(d, ddof=ddof) for d in _rdat]
res = nf(_ndat, axis=1, ddof=ddof)
assert_almost_equal(res, tgt)
def test_ddof_too_big(self):
nanfuncs = [np.nanvar, np.nanstd]
stdfuncs = [np.var, np.std]
dsize = [len(d) for d in _rdat]
for nf, rf in zip(nanfuncs, stdfuncs):
for ddof in range(5):
with suppress_warnings() as sup:
sup.record(RuntimeWarning)
sup.filter(ComplexWarning)
tgt = [ddof >= d for d in dsize]
res = nf(_ndat, axis=1, ddof=ddof)
assert_equal(np.isnan(res), tgt)
if any(tgt):
assert_(len(sup.log) == 1)
else:
assert_(len(sup.log) == 0)
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan),
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
match = "(Degrees of freedom <= 0 for slice.)|(Mean of empty slice)"
for func in self.nanfuncs:
with pytest.warns(RuntimeWarning, match=match):
out = func(array, axis=axis)
assert np.isnan(out).all()
if func is np.nanmean:
assert out.dtype == array.dtype
else:
assert out.dtype == np.abs(array).dtype
def test_empty(self):
mat = np.zeros((0, 3))
for f in self.nanfuncs:
for axis in [0, None]:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_(np.isnan(f(mat, axis=axis)).all())
assert_(len(w) == 1)
assert_(issubclass(w[0].category, RuntimeWarning))
for axis in [1]:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_equal(f(mat, axis=axis), np.zeros([]))
assert_(len(w) == 0)
def test_where(self, dtype):
ar = np.arange(9).reshape(3, 3).astype(dtype)
ar[0, :] = np.nan
where = np.ones_like(ar, dtype=np.bool)
where[:, 0] = False
for f, f_std in zip(self.nanfuncs, self.stdfuncs):
reference = f_std(ar[where][2:])
dtype_reference = dtype if f is np.nanmean else ar.real.dtype
ret = f(ar, where=where)
assert ret.dtype == dtype_reference
def test_nanstd_with_mean_keyword(self):
rng = np.random.RandomState(1234)
A = rng.randn(10, 20, 5) + 0.5
A[:, 5, :] = np.nan
mean_out = np.zeros((10, 1, 5))
std_out = np.zeros((10, 1, 5))
mean = np.nanmean(A,
out=mean_out,
axis=1,
keepdims=True)
assert mean_out is mean
std = np.nanstd(A,
out=std_out,
axis=1,
keepdims=True,
mean=mean)
assert std_out is std
assert std.shape == mean.shape
assert std.shape == (10, 1, 5)
std_old = np.nanstd(A, axis=1, keepdims=True)
assert std_old.shape == mean.shape
_TIME_UNITS = (
"Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as"
)
_TYPE_CODES = list(np.typecodes["AllFloat"])
_TYPE_CODES += [f"m8[{unit}]" for unit in _TIME_UNITS]
class TestNanFunctions_Median:
def test_mutation(self):
ndat = _ndat.copy()
np.nanmedian(ndat)
assert_equal(ndat, _ndat)
def test_keepdims(self):
mat = np.eye(3)
for axis in [None, 0, 1]:
tgt = np.median(mat, axis=axis, out=None, overwrite_input=False)
res = np.nanmedian(mat, axis=axis, out=None, overwrite_input=False)
assert_(res.ndim == tgt.ndim)
d = np.ones((3, 5, 7, 11))
w = np.random.random((4, 200)) * np.array(d.shape)[:, None]
w = w.astype(np.intp)
d[tuple(w)] = np.nan
with suppress_warnings() as sup:
sup.filter(RuntimeWarning)
res = np.nanmedian(d, axis=None, keepdims=True)
assert_equal(res.shape, (1, 1, 1, 1))
res = np.nanmedian(d, axis=(0, 1), keepdims=True)
assert_equal(res.shape, (1, 1, 7, 11))
res = np.nanmedian(d, axis=(0, 3), keepdims=True)
assert_equal(res.shape, (1, 5, 7, 1))
res = np.nanmedian(d, axis=(1,), keepdims=True)
assert_equal(res.shape, (3, 1, 7, 11))
res = np.nanmedian(d, axis=(0, 1, 2, 3), keepdims=True)
assert_equal(res.shape, (1, 1, 1, 1))
res = np.nanmedian(d, axis=(0, 1, 3), keepdims=True)
assert_equal(res.shape, (1, 1, 7, 1))
@pytest.mark.parametrize(
argnames='axis',
argvalues=[
None,
1,
(1, ),
(0, 1),
(-3, -1),
]
)
@pytest.mark.filterwarnings("ignore:All-NaN slice:RuntimeWarning")
def test_keepdims_out(self, axis):
d = np.ones((3, 5, 7, 11))
w = np.random.random((4, 200)) * np.array(d.shape)[:, None]
w = w.astype(np.intp)
d[tuple(w)] = np.nan
if axis is None:
shape_out = (1,) * d.ndim
else:
axis_norm = normalize_axis_tuple(axis, d.ndim)
shape_out = tuple(
1 if i in axis_norm else d.shape[i] for i in range(d.ndim))
out = np.empty(shape_out)
result = np.nanmedian(d, axis=axis, keepdims=True, out=out)
assert result is out
assert_equal(result.shape, shape_out)
def test_out(self):
mat = np.random.rand(3, 3)
nan_mat = np.insert(mat, [0, 2], np.nan, axis=1)
resout = np.zeros(3)
tgt = np.median(mat, axis=1)
res = np.nanmedian(nan_mat, axis=1, out=resout)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
resout = np.zeros(())
tgt = np.median(mat, axis=None)
res = np.nanmedian(nan_mat, axis=None, out=resout)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
res = np.nanmedian(nan_mat, axis=(0, 1), out=resout)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
def test_small_large(self):
for s in [5, 20, 51, 200, 1000]:
d = np.random.randn(4, s)
w = np.random.randint(0, d.size, size=d.size // 5)
d.ravel()[w] = np.nan
d[:, 0] = 1.
tgt = []
for x in d:
nonan = np.compress(~np.isnan(x), x)
tgt.append(np.median(nonan, overwrite_input=True))
assert_array_equal(np.nanmedian(d, axis=-1), tgt)
def test_result_values(self):
tgt = [np.median(d) for d in _rdat]
res = np.nanmedian(_ndat, axis=1)
assert_almost_equal(res, tgt)
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", _TYPE_CODES)
def test_allnans(self, dtype, axis):
mat = np.full((3, 3), np.nan).astype(dtype)
with suppress_warnings() as sup:
sup.record(RuntimeWarning)
output = np.nanmedian(mat, axis=axis)
assert output.dtype == mat.dtype
assert np.isnan(output).all()
if axis is None:
assert_(len(sup.log) == 1)
else:
assert_(len(sup.log) == 3)
scalar = np.array(np.nan).astype(dtype)[()]
output_scalar = np.nanmedian(scalar)
assert output_scalar.dtype == scalar.dtype
assert np.isnan(output_scalar)
if axis is None:
assert_(len(sup.log) == 2)
else:
assert_(len(sup.log) == 4)
def test_empty(self):
mat = np.zeros((0, 3))
for axis in [0, None]:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_(np.isnan(np.nanmedian(mat, axis=axis)).all())
assert_(len(w) == 1)
assert_(issubclass(w[0].category, RuntimeWarning))
for axis in [1]:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_equal(np.nanmedian(mat, axis=axis), np.zeros([]))
assert_(len(w) == 0)
def test_scalar(self):
assert_(np.nanmedian(0.) == 0.)
def test_extended_axis_invalid(self):
d = np.ones((3, 5, 7, 11))
assert_raises(AxisError, np.nanmedian, d, axis=-5)
assert_raises(AxisError, np.nanmedian, d, axis=(0, -5))
assert_raises(AxisError, np.nanmedian, d, axis=4)
assert_raises(AxisError, np.nanmedian, d, axis=(0, 4))
assert_raises(ValueError, np.nanmedian, d, axis=(1, 1))
def test_float_special(self):
with suppress_warnings() as sup:
sup.filter(RuntimeWarning)
for inf in [np.inf, -np.inf]:
a = np.array([[inf, np.nan], [np.nan, np.nan]])
assert_equal(np.nanmedian(a, axis=0), [inf, np.nan])
assert_equal(np.nanmedian(a, axis=1), [inf, np.nan])
assert_equal(np.nanmedian(a), inf)
a = np.array([[np.nan, np.nan, inf],
[np.nan, np.nan, inf]])
assert_equal(np.nanmedian(a), inf)
assert_equal(np.nanmedian(a, axis=0), [np.nan, np.nan, inf])
assert_equal(np.nanmedian(a, axis=1), inf)
a = np.array([[inf, inf], [inf, inf]])
assert_equal(np.nanmedian(a, axis=1), inf)
a = np.array([[inf, 7, -inf, -9],
[-10, np.nan, np.nan, 5],
[4, np.nan, np.nan, inf]],
dtype=np.float32)
if inf > 0:
assert_equal(np.nanmedian(a, axis=0), [4., 7., -inf, 5.])
assert_equal(np.nanmedian(a), 4.5)
else:
assert_equal(np.nanmedian(a, axis=0), [-10., 7., -inf, -9.])
assert_equal(np.nanmedian(a), -2.5)
assert_equal(np.nanmedian(a, axis=-1), [-1., -2.5, inf])
for i in range(0, 10):
for j in range(1, 10):
a = np.array([([np.nan] * i) + ([inf] * j)] * 2)
assert_equal(np.nanmedian(a), inf)
assert_equal(np.nanmedian(a, axis=1), inf)
assert_equal(np.nanmedian(a, axis=0),
([np.nan] * i) + [inf] * j)
a = np.array([([np.nan] * i) + ([-inf] * j)] * 2)
assert_equal(np.nanmedian(a), -inf)
assert_equal(np.nanmedian(a, axis=1), -inf)
assert_equal(np.nanmedian(a, axis=0),
([np.nan] * i) + [-inf] * j)
class TestNanFunctions_Percentile:
def test_mutation(self):
ndat = _ndat.copy()
np.nanpercentile(ndat, 30)
assert_equal(ndat, _ndat)
def test_keepdims(self):
mat = np.eye(3)
for axis in [None, 0, 1]:
tgt = np.percentile(mat, 70, axis=axis, out=None,
overwrite_input=False)
res = np.nanpercentile(mat, 70, axis=axis, out=None,
overwrite_input=False)
assert_(res.ndim == tgt.ndim)
d = np.ones((3, 5, 7, 11))
w = np.random.random((4, 200)) * np.array(d.shape)[:, None]
w = w.astype(np.intp)
d[tuple(w)] = np.nan
with suppress_warnings() as sup:
sup.filter(RuntimeWarning)
res = np.nanpercentile(d, 90, axis=None, keepdims=True)
assert_equal(res.shape, (1, 1, 1, 1))
res = np.nanpercentile(d, 90, axis=(0, 1), keepdims=True)
assert_equal(res.shape, (1, 1, 7, 11))
res = np.nanpercentile(d, 90, axis=(0, 3), keepdims=True)
assert_equal(res.shape, (1, 5, 7, 1))
res = np.nanpercentile(d, 90, axis=(1,), keepdims=True)
assert_equal(res.shape, (3, 1, 7, 11))
res = np.nanpercentile(d, 90, axis=(0, 1, 2, 3), keepdims=True)
assert_equal(res.shape, (1, 1, 1, 1))
res = np.nanpercentile(d, 90, axis=(0, 1, 3), keepdims=True)
assert_equal(res.shape, (1, 1, 7, 1))
@pytest.mark.parametrize('q', [7, [1, 7]])
@pytest.mark.parametrize(
argnames='axis',
argvalues=[
None,
1,
(1,),
(0, 1),
(-3, -1),
]
)
@pytest.mark.filterwarnings("ignore:All-NaN slice:RuntimeWarning")
def test_keepdims_out(self, q, axis):
d = np.ones((3, 5, 7, 11))
w = np.random.random((4, 200)) * np.array(d.shape)[:, None]
w = w.astype(np.intp)
d[tuple(w)] = np.nan
if axis is None:
shape_out = (1,) * d.ndim
else:
axis_norm = normalize_axis_tuple(axis, d.ndim)
shape_out = tuple(
1 if i in axis_norm else d.shape[i] for i in range(d.ndim))
shape_out = np.shape(q) + shape_out
out = np.empty(shape_out)
result = np.nanpercentile(d, q, axis=axis, keepdims=True, out=out)
assert result is out
assert_equal(result.shape, shape_out)
@pytest.mark.parametrize("weighted", [False, True])
def test_out(self, weighted):
mat = np.random.rand(3, 3)
nan_mat = np.insert(mat, [0, 2], np.nan, axis=1)
resout = np.zeros(3)
if weighted:
w_args = {"weights": np.ones_like(mat), "method": "inverted_cdf"}
nan_w_args = {
"weights": np.ones_like(nan_mat), "method": "inverted_cdf"
}
else:
w_args = dict()
nan_w_args = dict()
tgt = np.percentile(mat, 42, axis=1, **w_args)
res = np.nanpercentile(nan_mat, 42, axis=1, out=resout, **nan_w_args)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
resout = np.zeros(())
tgt = np.percentile(mat, 42, axis=None, **w_args)
res = np.nanpercentile(
nan_mat, 42, axis=None, out=resout, **nan_w_args
)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
res = np.nanpercentile(
nan_mat, 42, axis=(0, 1), out=resout, **nan_w_args
)
assert_almost_equal(res, resout)
assert_almost_equal(res, tgt)
def test_complex(self):
arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='G')
assert_raises(TypeError, np.nanpercentile, arr_c, 0.5)
arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='D')
assert_raises(TypeError, np.nanpercentile, arr_c, 0.5)
arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='F')
assert_raises(TypeError, np.nanpercentile, arr_c, 0.5)
@pytest.mark.parametrize("weighted", [False, True])
@pytest.mark.parametrize("use_out", [False, True])
def test_result_values(self, weighted, use_out):
if weighted:
percentile = partial(np.percentile, method="inverted_cdf")
nanpercentile = partial(np.nanpercentile, method="inverted_cdf")
def gen_weights(d):
return np.ones_like(d)
else:
percentile = np.percentile
nanpercentile = np.nanpercentile
def gen_weights(d):
return None
tgt = [percentile(d, 28, weights=gen_weights(d)) for d in _rdat]
out = np.empty_like(tgt) if use_out else None
res = nanpercentile(_ndat, 28, axis=1,
weights=gen_weights(_ndat), out=out)
assert_almost_equal(res, tgt)
tgt = np.transpose([percentile(d, (28, 98), weights=gen_weights(d))
for d in _rdat])
out = np.empty_like(tgt) if use_out else None
res = nanpercentile(_ndat, (28, 98), axis=1,
weights=gen_weights(_ndat), out=out)
assert_almost_equal(res, tgt)
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["Float"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan),
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
with pytest.warns(RuntimeWarning, match="All-NaN slice encountered"):
out = np.nanpercentile(array, 60, axis=axis)
assert np.isnan(out).all()
assert out.dtype == array.dtype
def test_empty(self):
mat = np.zeros((0, 3))
for axis in [0, None]:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_(np.isnan(np.nanpercentile(mat, 40, axis=axis)).all())
assert_(len(w) == 1)
assert_(issubclass(w[0].category, RuntimeWarning))
for axis in [1]:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
assert_equal(np.nanpercentile(mat, 40, axis=axis), np.zeros([]))
assert_(len(w) == 0)
def test_scalar(self):
assert_equal(np.nanpercentile(0., 100), 0.)
a = np.arange(6)
r = np.nanpercentile(a, 50, axis=0)
assert_equal(r, 2.5)
assert_(np.isscalar(r))
def test_extended_axis_invalid(self):
d = np.ones((3, 5, 7, 11))
assert_raises(AxisError, np.nanpercentile, d, q=5, axis=-5)
assert_raises(AxisError, np.nanpercentile, d, q=5, axis=(0, -5))
assert_raises(AxisError, np.nanpercentile, d, q=5, axis=4)
assert_raises(AxisError, np.nanpercentile, d, q=5, axis=(0, 4))
assert_raises(ValueError, np.nanpercentile, d, q=5, axis=(1, 1))
def test_multiple_percentiles(self):
perc = [50, 100]
mat = np.ones((4, 3))
nan_mat = np.nan * mat
large_mat = np.ones((3, 4, 5))
large_mat[:, 0:2:4, :] = 0
large_mat[:, :, 3:] *= 2
for axis in [None, 0, 1]:
for keepdim in [False, True]:
with suppress_warnings() as sup:
sup.filter(RuntimeWarning, "All-NaN slice encountered")
val = np.percentile(mat, perc, axis=axis, keepdims=keepdim)
nan_val = np.nanpercentile(nan_mat, perc, axis=axis,
keepdims=keepdim)
assert_equal(nan_val.shape, val.shape)
val = np.percentile(large_mat, perc, axis=axis,
keepdims=keepdim)
nan_val = np.nanpercentile(large_mat, perc, axis=axis,
keepdims=keepdim)
assert_equal(nan_val, val)
megamat = np.ones((3, 4, 5, 6))
assert_equal(
np.nanpercentile(megamat, perc, axis=(1, 2)).shape, (2, 3, 6)
)
@pytest.mark.parametrize("nan_weight", [0, 1, 2, 3, 1e200])
def test_nan_value_with_weight(self, nan_weight):
x = [1, np.nan, 2, 3]
result = np.float64(2.0)
q_unweighted = np.nanpercentile(x, 50, method="inverted_cdf")
assert_equal(q_unweighted, result)
w = [1.0, nan_weight, 1.0, 1.0]
q_weighted = np.nanpercentile(x, 50, weights=w, method="inverted_cdf")
assert_equal(q_weighted, result)
def test_nan_value_with_weight_ndim(self, axis):
np.random.seed(1)
x_no_nan = np.random.random(size=(100, 99, 2))
x = x_no_nan.copy()
x[np.arange(99), np.arange(99), 0] = np.nan
weights = np.ones_like(x)
weights[np.isnan(x)] = 0
p_expected = np.percentile(
x_no_nan, p, axis=axis, weights=weights, method="inverted_cdf")
p_unweighted = np.nanpercentile(
x, p, axis=axis, method="inverted_cdf")
assert_equal(p_unweighted, p_expected)
weights[np.isnan(x)] = 1e200
p_weighted = np.nanpercentile(
x, p, axis=axis, weights=weights, method="inverted_cdf")
assert_equal(p_weighted, p_expected)
out = np.empty_like(p_weighted)
res = np.nanpercentile(
x, p, axis=axis, weights=weights, out=out, method="inverted_cdf")
assert res is out
assert_equal(out, p_expected)
class TestNanFunctions_Quantile:
@pytest.mark.parametrize("weighted", [False, True])
def test_regression(self, weighted):
ar = np.arange(24).reshape(2, 3, 4).astype(float)
ar[0][1] = np.nan
if weighted:
w_args = {"weights": np.ones_like(ar), "method": "inverted_cdf"}
else:
w_args = dict()
assert_equal(np.nanquantile(ar, q=0.5, **w_args),
np.nanpercentile(ar, q=50, **w_args))
assert_equal(np.nanquantile(ar, q=0.5, axis=0, **w_args),
np.nanpercentile(ar, q=50, axis=0, **w_args))
assert_equal(np.nanquantile(ar, q=0.5, axis=1, **w_args),
np.nanpercentile(ar, q=50, axis=1, **w_args))
assert_equal(np.nanquantile(ar, q=[0.5], axis=1, **w_args),
np.nanpercentile(ar, q=[50], axis=1, **w_args))
assert_equal(np.nanquantile(ar, q=[0.25, 0.5, 0.75], axis=1, **w_args),
np.nanpercentile(ar, q=[25, 50, 75], axis=1, **w_args))
def test_basic(self):
x = np.arange(8) * 0.5
assert_equal(np.nanquantile(x, 0), 0.)
assert_equal(np.nanquantile(x, 1), 3.5)
assert_equal(np.nanquantile(x, 0.5), 1.75)
def test_complex(self):
arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='G')
assert_raises(TypeError, np.nanquantile, arr_c, 0.5)
arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='D')
assert_raises(TypeError, np.nanquantile, arr_c, 0.5)
arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='F')
assert_raises(TypeError, np.nanquantile, arr_c, 0.5)
def test_no_p_overwrite(self):
p0 = np.array([0, 0.75, 0.25, 0.5, 1.0])
p = p0.copy()
np.nanquantile(np.arange(100.), p, method="midpoint")
assert_array_equal(p, p0)
p0 = p0.tolist()
p = p.tolist()
np.nanquantile(np.arange(100.), p, method="midpoint")
assert_array_equal(p, p0)
@pytest.mark.parametrize("axis", [None, 0, 1])
@pytest.mark.parametrize("dtype", np.typecodes["Float"])
@pytest.mark.parametrize("array", [
np.array(np.nan),
np.full((3, 3), np.nan),
], ids=["0d", "2d"])
def test_allnans(self, axis, dtype, array):
if axis is not None and array.ndim == 0:
pytest.skip(f"`axis != None` not supported for 0d arrays")
array = array.astype(dtype)
with pytest.warns(RuntimeWarning, match="All-NaN slice encountered"):
out = np.nanquantile(array, 1, axis=axis)
assert np.isnan(out).all()
assert out.dtype == array.dtype
(np.array([1, 5, 7, 9], dtype=np.int64),
True),
(np.array([False, True, False, True]),
True),
(np.array([[np.nan, 5.0],
[np.nan, np.inf]], dtype=np.complex64),
np.array([[False, True],
[False, True]])),
])
def test__nan_mask(arr, expected):
for out in [None, np.empty(arr.shape, dtype=np.bool)]:
actual = _nan_mask(arr, out=out)
assert_equal(actual, expected)
if type(expected) is not np.ndarray:
assert actual is True
def test__replace_nan():
""" Test that _replace_nan returns the original array if there are no
NaNs, not a copy.
"""
for dtype in [np.bool, np.int32, np.int64]:
arr = np.array([0, 1], dtype=dtype)
result, mask = _replace_nan(arr, 0)
assert mask is None
assert result is arr
for dtype in [np.float32, np.float64]:
arr = np.array([0, 1], dtype=dtype)
result, mask = _replace_nan(arr, 2)
assert (mask == False).all()
assert result is not arr
assert_equal(result, arr)
arr_nan = np.array([0, 1, np.nan], dtype=dtype)
result_nan, mask_nan = _replace_nan(arr_nan, 2)
assert_equal(mask_nan, np.array([False, False, True]))
assert result_nan is not arr_nan
assert_equal(result_nan, np.array([0, 1, 2]))
assert np.isnan(arr_nan[-1])
.\numpy\numpy\lib\tests\test_packbits.py
import numpy as np
from numpy.testing import assert_array_equal, assert_equal, assert_raises
import pytest
from itertools import chain
def test_packbits():
a = [[[1, 0, 1], [0, 1, 0]],
[[1, 1, 0], [0, 0, 1]]]
for dt in '?bBhHiIlLqQ':
arr = np.array(a, dtype=dt)
b = np.packbits(arr, axis=-1)
assert_equal(b.dtype, np.uint8)
assert_array_equal(b, np.array([[[160], [64]], [[192], [32]]]))
assert_raises(TypeError, np.packbits, np.array(a, dtype=float))
def test_packbits_empty():
shapes = [
(0,), (10, 20, 0), (10, 0, 20), (0, 10, 20), (20, 0, 0), (0, 20, 0),
(0, 0, 20), (0, 0, 0),
]
for dt in '?bBhHiIlLqQ':
for shape in shapes:
a = np.empty(shape, dtype=dt)
b = np.packbits(a)
assert_equal(b.dtype, np.uint8)
assert_equal(b.shape, (0,))
def test_packbits_empty_with_axis():
shapes = [
((0,), [(0,)]),
((10, 20, 0), [(2, 20, 0), (10, 3, 0), (10, 20, 0)]),
((10, 0, 20), [(2, 0, 20), (10, 0, 20), (10, 0, 3)]),
((0, 10, 20), [(0, 10, 20), (0, 2, 20), (0, 10, 3)]),
((20, 0, 0), [(3, 0, 0), (20, 0, 0), (20, 0, 0)]),
((0, 20, 0), [(0, 20, 0), (0, 3, 0), (0, 20, 0)]),
((0, 0, 20), [(0, 0, 20), (0, 0, 20), (0, 0, 3)]),
((0, 0, 0), [(0, 0, 0), (0, 0, 0), (0, 0, 0)]),
]
for dt in '?bBhHiIlLqQ':
for in_shape, out_shapes in shapes:
for ax, out_shape in enumerate(out_shapes):
a = np.empty(in_shape, dtype=dt)
b = np.packbits(a, axis=ax)
assert_equal(b.dtype, np.uint8)
assert_equal(b.shape, out_shape)
@pytest.mark.parametrize('bitorder', ('little', 'big'))
def test_packbits_large(bitorder):
a = np.array([1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,
1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,
1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1,
1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1,
0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0,
1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1,
1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1,
1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0])
a = a.repeat(3)
for dtype in 'bBhHiIlLqQ':
arr = np.array(a, dtype=dtype)
rnd = np.random.randint(low=np.iinfo(dtype).min,
high=np.iinfo(dtype).max, size=arr.size,
dtype=dtype)
rnd[rnd == 0] = 1
arr *= rnd.astype(dtype)
b = np.packbits(arr, axis=-1)
assert_array_equal(np.unpackbits(b)[:-4], a)
assert_raises(TypeError, np.packbits, np.array(a, dtype=float))
def test_packbits_very_large():
for s in range(950, 1050):
for dt in '?bBhHiIlLqQ':
x = np.ones((200, s), dtype=bool)
np.packbits(x, axis=1)
def test_unpackbits():
a = np.array([[2], [7], [23]], dtype=np.uint8)
b = np.unpackbits(a, axis=1)
assert_equal(b.dtype, np.uint8)
assert_array_equal(b, np.array([[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 0, 1, 1, 1]]))
def test_pack_unpack_order():
a = np.array([[2], [7], [23]], dtype=np.uint8)
b = np.unpackbits(a, axis=1)
assert_equal(b.dtype, np.uint8)
b_big = np.unpackbits(a, axis=1, bitorder='big')
b_little = np.unpackbits(a, axis=1, bitorder='little')
assert_array_equal(b, b_big)
assert_array_equal(a, np.packbits(b_little, axis=1, bitorder='little'))
assert_array_equal(b[:,::-1], b_little)
assert_array_equal(a, np.packbits(b_big, axis=1, bitorder='big'))
assert_raises(ValueError, np.unpackbits, a, bitorder='r')
assert_raises(TypeError, np.unpackbits, a, bitorder=10)
def test_unpackbits_empty():
a = np.empty((0,), dtype=np.uint8)
b = np.unpackbits(a)
assert_equal(b.dtype, np.uint8)
assert_array_equal(b, np.empty((0,)))
def test_unpackbits_empty_with_axis():
shapes = [
([(0,)], (0,)),
([(2, 24, 0), (16, 3, 0), (16, 24, 0)], (16, 24, 0)),
([(2, 0, 24), (16, 0, 24), (16, 0, 3)], (16, 0, 24)),
([(0, 16, 24), (0, 2, 24), (0, 16, 3)], (0, 16, 24)),
([(3, 0, 0), (24, 0, 0), (24, 0, 0)], (24, 0, 0)),
([(0, 24, 0), (0, 3, 0), (0, 24, 0)], (0, 24, 0)),
([(0, 0, 24), (0, 0, 24), (0, 0, 3)], (0, 0, 24)),
([(0, 0, 0), (0, 0, 0), (0, 0, 0)], (0, 0, 0)),
]
for in_shapes, out_shape in shapes:
for ax, in_shape in enumerate(in_shapes):
a = np.empty(in_shape, dtype=np.uint8)
b = np.unpackbits(a, axis=ax)
assert_equal(b.dtype, np.uint8)
assert_equal(b.shape, out_shape)
def test_unpackbits_large():
d = np.arange(277, dtype=np.uint8)
assert_array_equal(np.packbits(np.unpackbits(d)), d)
assert_array_equal(np.packbits(np.unpackbits(d[::2])), d[::2])
d = np.tile(d, (3, 1))
assert_array_equal(np.packbits(np.unpackbits(d, axis=1), axis=1), d)
d = d.T.copy()
assert_array_equal(np.packbits(np.unpackbits(d, axis=0), axis=0), d)
class TestCount():
x = np.array([
[1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 0, 1, 0, 1, 0, 1],
[0, 0, 1, 1, 1, 0, 0],
[0, 1, 0, 1, 0, 1, 0],
], dtype=np.uint8)
padded1 = np.zeros(57, dtype=np.uint8)
padded1[:49] = x.ravel()
padded1b = np.zeros(57, dtype=np.uint8)
padded1b[:49] = x[::-1].copy().ravel()
padded2 = np.zeros((9, 9), dtype=np.uint8)
padded2[:7, :7] = x
@pytest.mark.parametrize('bitorder', ('little', 'big'))
@pytest.mark.parametrize('count', chain(range(58), range(-1, -57, -1)))
def test_roundtrip(self, bitorder, count):
if count < 0:
cutoff = count - 1
else:
cutoff = count
packed = np.packbits(self.x, bitorder=bitorder)
unpacked = np.unpackbits(packed, count=count, bitorder=bitorder)
assert_equal(unpacked.dtype, np.uint8)
assert_array_equal(unpacked, self.padded1[:cutoff])
@pytest.mark.parametrize('kwargs', [
{}, {'count': None},
])
def test_count(self, kwargs):
packed = np.packbits(self.x)
unpacked = np.unpackbits(packed, **kwargs)
assert_equal(unpacked.dtype, np.uint8)
assert_array_equal(unpacked, self.padded1[:-1])
@pytest.mark.parametrize('bitorder', ('little', 'big'))
@pytest.mark.parametrize('count', chain(range(8), range(-1, -9, -1)))
def test_roundtrip_axis(self, bitorder, count):
if count < 0:
cutoff = count - 1
else:
cutoff = count
packed0 = np.packbits(self.x, axis=0, bitorder=bitorder)
unpacked0 = np.unpackbits(packed0, axis=0, count=count,
bitorder=bitorder)
assert_equal(unpacked0.dtype, np.uint8)
assert_array_equal(unpacked0, self.padded2[:cutoff, :self.x.shape[1]])
packed1 = np.packbits(self.x, axis=1, bitorder=bitorder)
unpacked1 = np.unpackbits(packed1, axis=1, count=count,
bitorder=bitorder)
assert_equal(unpacked1.dtype, np.uint8)
assert_array_equal(unpacked1, self.padded2[:self.x.shape[0], :cutoff])
@pytest.mark.parametrize('kwargs', [
{}, {'count': None},
{'bitorder' : 'little'},
{'bitorder': 'little', 'count': None},
{'bitorder' : 'big'},
{'bitorder': 'big', 'count': None},
])
def test_axis_count(self, kwargs):
packed0 = np.packbits(self.x, axis=0)
unpacked0 = np.unpackbits(packed0, axis=0, **kwargs)
assert_equal(unpacked0.dtype, np.uint8)
if kwargs.get('bitorder', 'big') == 'big':
assert_array_equal(unpacked0, self.padded2[:-1, :self.x.shape[1]])
else:
assert_array_equal(unpacked0[::-1, :], self.padded2[:-1, :self.x.shape[1]])
packed1 = np.packbits(self.x, axis=1)
unpacked1 = np.unpackbits(packed1, axis=1, **kwargs)
assert_equal(unpacked1.dtype, np.uint8)
if kwargs.get('bitorder', 'big') == 'big':
assert_array_equal(unpacked1, self.padded2[:self.x.shape[0], :-1])
else:
assert_array_equal(unpacked1[:, ::-1], self.padded2[:self.x.shape[0], :-1])
def test_bad_count(self):
packed0 = np.packbits(self.x, axis=0)
assert_raises(ValueError, np.unpackbits, packed0, axis=0, count=-9)
packed1 = np.packbits(self.x, axis=1)
assert_raises(ValueError, np.unpackbits, packed1, axis=1, count=-9)
packed = np.packbits(self.x)
assert_raises(ValueError, np.unpackbits, packed, count=-57)
.\numpy\numpy\lib\tests\test_polynomial.py
import numpy as np
from numpy.testing import (
assert_, assert_equal, assert_array_equal, assert_almost_equal,
assert_array_almost_equal, assert_raises, assert_allclose
)
import pytest
TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O"
class TestPolynomial:
def test_poly1d_str_and_repr(self):
p = np.poly1d([1., 2, 3])
assert_equal(repr(p), 'poly1d([1., 2., 3.])')
assert_equal(str(p),
' 2\n'
'1 x + 2 x + 3')
q = np.poly1d([3., 2, 1])
assert_equal(repr(q), 'poly1d([3., 2., 1.])')
assert_equal(str(q),
' 2\n'
'3 x + 2 x + 1')
r = np.poly1d([1.89999 + 2j, -3j, -5.12345678, 2 + 1j])
assert_equal(str(r),
' 3 2\n'
'(1.9 + 2j) x - 3j x - 5.123 x + (2 + 1j)')
assert_equal(str(np.poly1d([-3, -2, -1])),
' 2\n'
'-3 x - 2 x - 1')
def test_poly1d_resolution(self):
p = np.poly1d([1., 2, 3])
q = np.poly1d([3., 2, 1])
assert_equal(p(0), 3.0)
assert_equal(p(5), 38.0)
assert_equal(q(0), 1.0)
assert_equal(q(5), 86.0)
def test_poly1d_math(self):
p = np.poly1d([1., 2, 4])
q = np.poly1d([4., 2, 1])
assert_equal(p/q, (np.poly1d([0.25]), np.poly1d([1.5, 3.75])))
assert_equal(p.integ(), np.poly1d([1/3, 1., 4., 0.]))
assert_equal(p.integ(1), np.poly1d([1/3, 1., 4., 0.]))
p = np.poly1d([1., 2, 3])
q = np.poly1d([3., 2, 1])
assert_equal(p * q, np.poly1d([3., 8., 14., 8., 3.]))
assert_equal(p + q, np.poly1d([4., 4., 4.]))
assert_equal(p - q, np.poly1d([-2., 0., 2.]))
assert_equal(p ** 4, np.poly1d([1., 8., 36., 104., 214., 312., 324., 216., 81.]))
assert_equal(p(q), np.poly1d([9., 12., 16., 8., 6.]))
assert_equal(q(p), np.poly1d([3., 12., 32., 40., 34.]))
assert_equal(p.deriv(), np.poly1d([2., 2.]))
assert_equal(p.deriv(2), np.poly1d([2.]))
assert_equal(np.polydiv(np.poly1d([1, 0, -1]), np.poly1d([1, 1])),
(np.poly1d([1., -1.]), np.poly1d([0.])))
@pytest.mark.parametrize("type_code", TYPE_CODES)
def test_poly1d_misc(self, type_code: str) -> None:
dtype = np.dtype(type_code)
ar = np.array([1, 2, 3], dtype=dtype)
p = np.poly1d(ar)
assert_equal(np.asarray(p), ar)
assert_equal(np.asarray(p).dtype, dtype)
assert_equal(len(p), 2)
comparison_dct = {-1: 0, 0: 3, 1: 2, 2: 1, 3: 0}
for index, ref in comparison_dct.items():
scalar = p[index]
assert_equal(scalar, ref)
if dtype == np.object_:
assert isinstance(scalar, int)
else:
assert_equal(scalar.dtype, dtype)
def test_poly1d_variable_arg(self):
q = np.poly1d([1., 2, 3], variable='y')
assert_equal(str(q),
' 2\n'
'1 y + 2 y + 3')
q = np.poly1d([1., 2, 3], variable='lambda')
assert_equal(str(q),
' 2\n'
'1 lambda + 2 lambda + 3')
def test_poly(self):
assert_array_almost_equal(np.poly([3, -np.sqrt(2), np.sqrt(2)]),
[1, -3, -2, 6])
A = [[1, 2, 3], [4, 5, 6], [7, 8, 0]]
assert_array_almost_equal(np.poly(A), [1, -6, -72, -27])
assert_(np.isrealobj(np.poly([+1.082j, +2.613j, -2.613j, -1.082j])))
assert_(np.isrealobj(np.poly([0+1j, -0+-1j, 1+2j,
1-2j, 1.+3.5j, 1-3.5j])))
assert_(np.isrealobj(np.poly([1j, -1j, 1+2j, 1-2j, 1+3j, 1-3.j])))
assert_(np.isrealobj(np.poly([1j, -1j, 2j, -2j])))
assert_(np.isrealobj(np.poly([1j, -1j])))
assert_(np.isrealobj(np.poly([1, -1])))
assert_(np.iscomplexobj(np.poly([1j, -1.0000001j])))
np.random.seed(42)
a = np.random.randn(100) + 1j*np.random.randn(100)
assert_(np.isrealobj(np.poly(np.concatenate((a, np.conjugate(a))))))
def test_roots(self):
assert_array_equal(np.roots([1, 0, 0]), [0, 0])
def test_str_leading_zeros(self):
p = np.poly1d([4, 3, 2, 1])
p[3] = 0
assert_equal(str(p),
" 2\n"
"3 x + 2 x + 1")
p = np.poly1d([1, 2])
p[0] = 0
p[1] = 0
assert_equal(str(p), " \n0")
def test_objects(self):
from decimal import Decimal
p = np.poly1d([Decimal('4.0'), Decimal('3.0'), Decimal('2.0')])
p2 = p * Decimal('1.333333333333333')
assert_(p2[1] == Decimal("3.9999999999999990"))
p2 = p.deriv()
assert_(p2[1] == Decimal('8.0'))
p2 = p.integ()
assert_(p2[3] == Decimal("1.333333333333333333333333333"))
assert_(p2[2] == Decimal('1.5'))
assert_(np.issubdtype(p2.coeffs.dtype, np.object_))
assert_equal(np.poly([Decimal(1), Decimal(2)]),
[1, Decimal(-3), Decimal(2)])
def test_complex(self):
p = np.poly1d([3j, 2j, 1j])
p2 = p.integ()
assert_((p2.coeffs == [1j, 1j, 1j, 0]).all())
p2 = p.deriv()
assert_((p2.coeffs == [6j, 2j]).all())
def test_integ_coeffs(self):
p = np.poly1d([3, 2, 1])
p2 = p.integ(3, k=[9, 7, 6])
assert_(
(p2.coeffs == [1/4./5., 1/3./4., 1/2./3., 9/1./2., 7, 6]).all())
def test_zero_dims(self):
try:
np.poly(np.zeros((0, 0)))
except ValueError:
pass
def test_poly_int_overflow(self):
"""
Regression test for gh-5096.
"""
v = np.arange(1, 21)
assert_almost_equal(np.poly(v), np.poly(np.diag(v)))
def test_zero_poly_dtype(self):
"""
Regression test for gh-16354.
"""
z = np.array([0, 0, 0])
p = np.poly1d(z.astype(np.int64))
assert_equal(p.coeffs.dtype, np.int64)
p = np.poly1d(z.astype(np.float32))
assert_equal(p.coeffs.dtype, np.float32)
p = np.poly1d(z.astype(np.complex64))
assert_equal(p.coeffs.dtype, np.complex64)
def test_poly_eq(self):
p = np.poly1d([1, 2, 3])
p2 = np.poly1d([1, 2, 4])
assert_equal(p == None, False)
assert_equal(p != None, True)
assert_equal(p == p, True)
assert_equal(p == p2, False)
assert_equal(p != p2, True)
def test_polydiv(self):
b = np.poly1d([2, 6, 6, 1])
a = np.poly1d([-1j, (1+2j), -(2+1j), 1])
q, r = np.polydiv(b, a)
assert_equal(q.coeffs.dtype, np.complex128)
assert_equal(r.coeffs.dtype, np.complex128)
assert_equal(q*a + r, b)
c = [1, 2, 3]
d = np.poly1d([1, 2, 3])
s, t = np.polydiv(c, d)
assert isinstance(s, np.poly1d)
assert isinstance(t, np.poly1d)
u, v = np.polydiv(d, c)
assert isinstance(u, np.poly1d)
assert isinstance(v, np.poly1d)
def test_poly_coeffs_mutable(self):
""" 测试多项式系数是否可修改 """
p = np.poly1d([1, 2, 3])
p.coeffs += 1
assert_equal(p.coeffs, [2, 3, 4])
p.coeffs[2] += 10
assert_equal(p.coeffs, [2, 3, 14])
assert_raises(AttributeError, setattr, p, 'coeffs', np.array(1))
.\numpy\numpy\lib\tests\test_recfunctions.py
import pytest
import numpy as np
import numpy.ma as ma
from numpy.ma.mrecords import MaskedRecords
from numpy.ma.testutils import assert_equal
from numpy.testing import assert_, assert_raises
from numpy.lib.recfunctions import (
drop_fields, rename_fields, get_fieldstructure, recursive_fill_fields,
find_duplicates, merge_arrays, append_fields, stack_arrays, join_by,
repack_fields, unstructured_to_structured, structured_to_unstructured,
apply_along_fields, require_fields, assign_fields_by_name)
get_fieldspec = np.lib.recfunctions._get_fieldspec
get_names = np.lib.recfunctions.get_names
get_names_flat = np.lib.recfunctions.get_names_flat
zip_descr = np.lib.recfunctions._zip_descr
zip_dtype = np.lib.recfunctions._zip_dtype
class TestRecFunctions:
def setup_method(self):
x = np.array([1, 2, ])
y = np.array([10, 20, 30])
z = np.array([('A', 1.), ('B', 2.)],
dtype=[('A', '|S3'), ('B', float)])
w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
self.data = (w, x, y, z)
def test_zip_descr(self):
(w, x, y, z) = self.data
test = zip_descr((x, x), flatten=True)
assert_equal(test,
np.dtype([('', int), ('', int)]))
test = zip_descr((x, x), flatten=False)
assert_equal(test,
np.dtype([('', int), ('', int)]))
test = zip_descr((x, z), flatten=True)
assert_equal(test,
np.dtype([('', int), ('A', '|S3'), ('B', float)]))
test = zip_descr((x, z), flatten=False)
assert_equal(test,
np.dtype([('', int),
('', [('A', '|S3'), ('B', float)])]))
test = zip_descr((x, w), flatten=True)
assert_equal(test,
np.dtype([('', int),
('a', int),
('ba', float), ('bb', int)]))
test = zip_descr((x, w), flatten=False)
assert_equal(test,
np.dtype([('', int),
('', [('a', int),
('b', [('ba', float), ('bb', int)])])]))
def test_drop_fields(self):
a = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
test = drop_fields(a, 'a')
control = np.array([((2, 3.0),), ((5, 6.0),)],
dtype=[('b', [('ba', float), ('bb', int)])])
assert_equal(test, control)
test = drop_fields(a, 'b')
control = np.array([(1,), (4,)], dtype=[('a', int)])
assert_equal(test, control)
test = drop_fields(a, ['ba', ])
control = np.array([(1, (3.0,)), (4, (6.0,))],
dtype=[('a', int), ('b', [('bb', int)])])
assert_equal(test, control)
test = drop_fields(a, ['ba', 'bb'])
control = np.array([(1,), (4,)], dtype=[('a', int)])
assert_equal(test, control)
test = drop_fields(a, ['a', 'b'])
control = np.array([(), ()], dtype=[])
assert_equal(test, control)
def test_rename_fields(self):
a = np.array([(1, (2, [3.0, 30.])), (4, (5, [6.0, 60.]))],
dtype=[('a', int),
('b', [('ba', float), ('bb', (float, 2))])])
test = rename_fields(a, {'a': 'A', 'bb': 'BB'})
newdtype = [('A', int), ('b', [('ba', float), ('BB', (float, 2))])]
control = a.view(newdtype)
assert_equal(test.dtype, newdtype)
assert_equal(test, control)
def test_get_names(self):
ndtype = np.dtype([('A', '|S3'), ('B', float)])
test = get_names(ndtype)
assert_equal(test, ('A', 'B'))
ndtype = np.dtype([('a', int), ('b', [('ba', float), ('bb', int)])])
test = get_names(ndtype)
assert_equal(test, ('a', ('b', ('ba', 'bb'))))
ndtype = np.dtype([('a', int), ('b', [])])
test = get_names(ndtype)
assert_equal(test, ('a', ('b', ())))
ndtype = np.dtype([])
test = get_names(ndtype)
assert_equal(test, ())
def test_get_names_flat(self):
ndtype = np.dtype([('A', '|S3'), ('B', float)])
test = get_names_flat(ndtype)
assert_equal(test, ('A', 'B'))
ndtype = np.dtype([('a', int), ('b', [('ba', float), ('bb', int)])])
test = get_names_flat(ndtype)
assert_equal(test, ('a', 'b', 'ba', 'bb'))
ndtype = np.dtype([('a', int), ('b', [])])
test = get_names_flat(ndtype)
assert_equal(test, ('a', 'b'))
ndtype = np.dtype([])
test = get_names_flat(ndtype)
assert_equal(test, ())
def test_get_fieldstructure(self):
ndtype = np.dtype([('A', '|S3'), ('B', float)])
test = get_fieldstructure(ndtype)
assert_equal(test, {'A': [], 'B': []})
ndtype = np.dtype([('A', int), ('B', [('BA', float), ('BB', '|S1')])])
test = get_fieldstructure(ndtype)
assert_equal(test, {'A': [], 'B': [], 'BA': ['B', ], 'BB': ['B']})
ndtype = np.dtype([('A', int),
('B', [('BA', int),
('BB', [('BBA', int), ('BBB', int)])])])
test = get_fieldstructure(ndtype)
control = {'A': [], 'B': [], 'BA': ['B'], 'BB': ['B'],
'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
assert_equal(test, control)
ndtype = np.dtype([])
test = get_fieldstructure(ndtype)
assert_equal(test, {})
def test_find_duplicates(self):
a = ma.array([(2, (2., 'B')), (1, (2., 'B')), (2, (2., 'B')),
(1, (1., 'B')), (2, (2., 'B')), (2, (2., 'C'))],
mask=[(0, (0, 0)), (0, (0, 0)), (0, (0, 0)),
(0, (0, 0)), (1, (0, 0)), (0, (1, 0))],
dtype=[('A', int), ('B', [('BA', float), ('BB', '|S1')])])
test = find_duplicates(a, ignoremask=False, return_index=True)
control = [0, 2]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
test = find_duplicates(a, key='A', return_index=True)
control = [0, 1, 2, 3, 5]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
test = find_duplicates(a, key='B', return_index=True)
control = [0, 1, 2, 4]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
test = find_duplicates(a, key='BA', return_index=True)
control = [0, 1, 2, 4]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
test = find_duplicates(a, key='BB', return_index=True)
control = [0, 1, 2, 3, 4]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
def test_find_duplicates_ignoremask(self):
ndtype = [('a', int)]
a = ma.array([1, 1, 1, 2, 2, 3, 3],
mask=[0, 0, 1, 0, 0, 0, 1]).view(ndtype)
test = find_duplicates(a, ignoremask=True, return_index=True)
control = [0, 1, 3, 4]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
test = find_duplicates(a, ignoremask=False, return_index=True)
control = [0, 1, 2, 3, 4, 6]
assert_equal(sorted(test[-1]), control)
assert_equal(test[0], a[test[-1]])
def test_repack_fields(self):
dt = np.dtype('u1,f4,i8', align=True)
a = np.zeros(2, dtype=dt)
assert_equal(repack_fields(dt), np.dtype('u1,f4,i8'))
assert_equal(repack_fields(a).itemsize, 13)
assert_equal(repack_fields(repack_fields(dt), align=True), dt)
dt = np.dtype((np.record, dt))
assert_(repack_fields(dt).type is np.record)
def test_unstructured_to_structured(self):
a = np.zeros((20, 2))
test_dtype_args = [('x', float), ('y', float)]
test_dtype = np.dtype(test_dtype_args)
field1 = unstructured_to_structured(a, dtype=test_dtype_args)
field2 = unstructured_to_structured(a, dtype=test_dtype)
assert_equal(field1, field2)
def test_field_assignment_by_name(self):
a = np.ones(2, dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'u1')])
newdt = [('b', 'f4'), ('c', 'u1')]
assert_equal(require_fields(a, newdt), np.ones(2, newdt))
b = np.array([(1,2), (3,4)], dtype=newdt)
assign_fields_by_name(a, b, zero_unassigned=False)
assert_equal(a, np.array([(1,1,2),(1,3,4)], dtype=a.dtype))
assign_fields_by_name(a, b)
assert_equal(a, np.array([(0,1,2),(0,3,4)], dtype=a.dtype))
a = np.ones(2, dtype=[('a', [('b', 'f8'), ('c', 'u1')])])
newdt = [('a', [('c', 'u1')])]
assert_equal(require_fields(a, newdt), np.ones(2, newdt))
b = np.array([((2,),), ((3,),)], dtype=newdt)
assign_fields_by_name(a, b, zero_unassigned=False)
assert_equal(a, np.array([((1,2),), ((1,3),)], dtype=a.dtype))
assign_fields_by_name(a, b)
assert_equal(a, np.array([((0,2),), ((0,3),)], dtype=a.dtype))
a, b = np.array(3), np.array(0)
assign_fields_by_name(b, a)
assert_equal(b[()], 3)
class TestRecursiveFillFields:
def test_simple_flexible(self):
a = np.array([(1, 10.), (2, 20.)], dtype=[('A', int), ('B', float)])
b = np.zeros((3,), dtype=a.dtype)
test = recursive_fill_fields(a, b)
control = np.array([(1, 10.), (2, 20.), (0, 0.)],
dtype=[('A', int), ('B', float)])
assert_equal(test, control)
def test_masked_flexible(self):
a = ma.array([(1, 10.), (2, 20.)], mask=[(0, 1), (1, 0)],
dtype=[('A', int), ('B', float)])
b = ma.zeros((3,), dtype=a.dtype)
test = recursive_fill_fields(a, b)
control = ma.array([(1, 10.), (2, 20.), (0, 0.)],
mask=[(0, 1), (1, 0), (0, 0)],
dtype=[('A', int), ('B', float)])
assert_equal(test, control)
class TestMergeArrays:
def setup_method(self):
x = np.array([1, 2, ])
y = np.array([10, 20, 30])
z = np.array(
[('A', 1.), ('B', 2.)], dtype=[('A', '|S3'), ('B', float)])
w = np.array(
[(1, (2, 3.0, ())), (4, (5, 6.0, ()))],
dtype=[('a', int), ('b', [('ba', float), ('bb', int), ('bc', [])])])
self.data = (w, x, y, z)
def test_solo(self):
(_, x, _, z) = self.data
test = merge_arrays(x)
control = np.array([(1,), (2,)], dtype=[('f0', int)])
assert_equal(test, control)
test = merge_arrays((x,))
assert_equal(test, control)
test = merge_arrays(z, flatten=False)
assert_equal(test, z)
test = merge_arrays(z, flatten=True)
assert_equal(test, z)
def test_solo_w_flatten(self):
w = self.data[0]
test = merge_arrays(w, flatten=False)
assert_equal(test, w)
test = merge_arrays(w, flatten=True)
control = np.array([(1, 2, 3.0), (4, 5, 6.0)],
dtype=[('a', int), ('ba', float), ('bb', int)])
assert_equal(test, control)
def test_standard(self):
(_, x, y, _) = self.data
test = merge_arrays((x, y), usemask=False)
control = np.array([(1, 10), (2, 20), (-1, 30)],
dtype=[('f0', int), ('f1', int)])
assert_equal(test, control)
test = merge_arrays((x, y), usemask=True)
control = ma.array([(1, 10), (2, 20), (-1, 30)],
mask=[(0, 0), (0, 0), (1, 0)],
dtype=[('f0', int), ('f1', int)])
assert_equal(test, control)
assert_equal(test.mask, control.mask)
def test_flatten(self):
(_, x, _, z) = self.data
test = merge_arrays((x, z), flatten=True)
control = np.array([(1, 'A', 1.), (2, 'B', 2.)],
dtype=[('f0', int), ('A', '|S3'), ('B', float)])
assert_equal(test, control)
test = merge_arrays((x, z), flatten=False)
control = np.array([(1, ('A', 1.)), (2, ('B', 2.))],
dtype=[('f0', int),
('f1', [('A', '|S3'), ('B', float)])])
assert_equal(test, control)
def test_flatten_wflexible(self):
(w, x, _, _) = self.data
test = merge_arrays((x, w), flatten=True)
control = np.array([(1, 1, 2, 3.0), (2, 4, 5, 6.0)],
dtype=[('f0', int),
('a', int), ('ba', float), ('bb', int)])
assert_equal(test, control)
test = merge_arrays((x, w), flatten=False)
controldtype = [('f0', int),
('f1', [('a', int),
('b', [('ba', float), ('bb', int), ('bc', [])])])]
control = np.array([(1., (1, (2, 3.0, ()))), (2, (4, (5, 6.0, ())))],
dtype=controldtype)
assert_equal(test, control)
def test_wmasked_arrays(self):
(_, x, _, _) = self.data
mx = ma.array([1, 2, 3], mask=[1, 0, 0])
test = merge_arrays((x, mx), usemask=True)
control = ma.array([(1, 1), (2, 2), (-1, 3)],
mask=[(0, 1), (0, 0), (1, 0)],
dtype=[('f0', int), ('f1', int)])
assert_equal(test, control)
test = merge_arrays((x, mx), usemask=True, asrecarray=True)
assert_equal(test, control)
assert_(isinstance(test, MaskedRecords))
def test_w_singlefield(self):
test = merge_arrays((np.array([1, 2]).view([('a', int)]),
np.array([10., 20., 30.])),)
control = ma.array([(1, 10.), (2, 20.), (-1, 30.)],
mask=[(0, 0), (0, 0), (1, 0)],
dtype=[('a', int), ('f1', float)])
assert_equal(test, control)
def test_w_shorter_flex(self):
z = self.data[-1]
merge_arrays((z, np.array([10, 20, 30]).view([('C', int)])))
np.array([('A', 1., 10), ('B', 2., 20), ('-1', -1, 20)],
dtype=[('A', '|S3'), ('B', float), ('C', int)])
def test_singlerecord(self):
(_, x, y, z) = self.data
test = merge_arrays((x[0], y[0], z[0]), usemask=False)
control = np.array([(1, 10, ('A', 1))],
dtype=[('f0', int),
('f1', int),
('f2', [('A', '|S3'), ('B', float)])])
assert_equal(test, control)
class TestAppendFields:
def setup_method(self):
x = np.array([1, 2, ])
y = np.array([10, 20, 30])
z = np.array(
[('A', 1.), ('B', 2.)], dtype=[('A', '|S3'), ('B', float)])
w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
self.data = (w, x, y, z)
def test_append_single(self):
(_, x, _, _) = self.data
test = append_fields(x, 'A', data=[10, 20, 30])
control = ma.array([(1, 10), (2, 20), (-1, 30)],
mask=[(0, 0), (0, 0), (1, 0)],
dtype=[('f0', int), ('A', int)],)
assert_equal(test, control)
def test_append_double(self):
(_, x, _, _) = self.data
test = append_fields(x, ('A', 'B'), data=[[10, 20, 30], [100, 200]])
control = ma.array([(1, 10, 100), (2, 20, 200), (-1, 30, -1)],
mask=[(0, 0, 0), (0, 0, 0), (1, 0, 1)],
dtype=[('f0', int), ('A', int), ('B', int)],)
assert_equal(test, control)
def test_append_on_flex(self):
z = self.data[-1]
test = append_fields(z, 'C', data=[10, 20, 30])
control = ma.array([('A', 1., 10), ('B', 2., 20), (-1, -1., 30)],
mask=[(0, 0, 0), (0, 0, 0), (1, 1, 0)],
dtype=[('A', '|S3'), ('B', float), ('C', int)],)
assert_equal(test, control)
def test_append_on_nested(self):
w = self.data[0]
test = append_fields(w, 'C', data=[10, 20, 30])
control = ma.array([(1, (2, 3.0), 10),
(4, (5, 6.0), 20),
(-1, (-1, -1.), 30)],
mask=[(
0, (0, 0), 0), (0, (0, 0), 0), (1, (1, 1), 0)],
dtype=[('a', int),
('b', [('ba', float), ('bb', int)]),
('C', int)],)
assert_equal(test, control)
class TestStackArrays:
def setup_method(self):
x = np.array([1, 2, ])
y = np.array([10, 20, 30])
z = np.array(
[('A', 1.), ('B', 2.)], dtype=[('A', '|S3'), ('B', float)])
w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
self.data = (w, x, y, z)
def test_solo(self):
(_, x, _, _) = self.data
test = stack_arrays((x,))
assert_equal(test, x)
assert_(test is x)
test = stack_arrays(x)
assert_equal(test, x)
assert_(test is x)
def test_unnamed_fields(self):
(_, x, y, _) = self.data
test = stack_arrays((x, x), usemask=False)
control = np.array([1, 2, 1, 2])
assert_equal(test, control)
test = stack_arrays((x, y), usemask=False)
control = np.array([1, 2, 10, 20, 30])
assert_equal(test, control)
test = stack_arrays((y, x), usemask=False)
control = np.array([10, 20, 30, 1, 2])
assert_equal(test, control)
def test_unnamed_and_named_fields(self):
(_, x, _, z) = self.data
test = stack_arrays((x, z))
control = ma.array([(1, -1, -1), (2, -1, -1),
(-1, 'A', 1), (-1, 'B', 2)],
mask=[(0, 1, 1), (0, 1, 1),
(1, 0, 0), (1, 0, 0)],
dtype=[('f0', int), ('A', '|S3'), ('B', float)])
assert_equal(test, control)
assert_equal(test.mask, control.mask)
test = stack_arrays((z, x))
control = ma.array([('A', 1, -1), ('B', 2, -1),
(-1, -1, 1), (-1, -1, 2), ],
mask=[(0, 0, 1), (0, 0, 1),
(1, 1, 0), (1, 1, 0)],
dtype=[('A', '|S3'), ('B', float), ('f2', int)])
assert_equal(test, control)
assert_equal(test.mask, control.mask)
test = stack_arrays((z, z, x))
control = ma.array([('A', 1, -1), ('B', 2, -1),
('A', 1, -1), ('B', 2, -1),
(-1, -1, 1), (-1, -1, 2), ],
mask=[(0, 0, 1), (0, 0, 1),
(0, 0, 1), (0, 0, 1),
(1, 1, 0), (1, 1, 0)],
dtype=[('A', '|S3'), ('B', float), ('f2', int)])
assert_equal(test, control)
def test_matching_named_fields(self):
(_, x, _, z) = self.data
zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
dtype=[('A', '|S3'), ('B', float), ('C', float)])
test = stack_arrays((z, zz))
control = ma.array([('A', 1, -1), ('B', 2, -1),
('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
dtype=[('A', '|S3'), ('B', float), ('C', float)],
mask=[(0, 0, 1), (0, 0, 1),
(0, 0, 0), (0, 0, 0), (0, 0, 0)])
assert_equal(test, control)
assert_equal(test.mask, control.mask)
test = stack_arrays((z, zz, x))
ndtype = [('A', '|S3'), ('B', float), ('C', float), ('f3', int)]
control = ma.array([('A', 1, -1, -1), ('B', 2, -1, -1),
('a', 10., 100., -1), ('b', 20., 200., -1),
('c', 30., 300., -1),
(-1, -1, -1, 1), (-1, -1, -1, 2)],
dtype=ndtype,
mask=[(0, 0, 1, 1), (0, 0, 1, 1),
(0, 0, 0, 1), (0, 0, 0, 1), (0, 0, 0, 1),
(1, 1, 1, 0), (1, 1, 1, 0)])
assert_equal(test, control)
assert_equal(test.mask, control.mask)
def test_defaults(self):
(_, _, _, z) = self.data
zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
dtype=[('A', '|S3'), ('B', float), ('C', float)])
defaults = {'A': '???', 'B': -999., 'C': -9999., 'D': -99999.}
test = stack_arrays((z, zz), defaults=defaults)
control = ma.array([('A', 1, -9999.), ('B', 2, -9999.),
('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
dtype=[('A', '|S3'), ('B', float), ('C', float)],
mask=[(0, 0, 1), (0, 0, 1),
(0, 0, 0), (0, 0, 0), (0, 0, 0)])
assert_equal(test, control)
assert_equal(test.data, control.data)
assert_equal(test.mask, control.mask)
def test_autoconversion(self):
adtype = [('A', int), ('B', bool), ('C', float)]
a = ma.array([(1, 2, 3)], mask=[(0, 1, 0)], dtype=adtype)
bdtype = [('A', int), ('B', float), ('C', float)]
b = ma.array([(4, 5, 6)], dtype=bdtype)
control = ma.array([(1, 2, 3), (4, 5, 6)], mask=[(0, 1, 0), (0, 0, 0)],
dtype=bdtype)
test = stack_arrays((a, b), autoconvert=True)
assert_equal(test, control)
assert_equal(test.mask, control.mask)
with assert_raises(TypeError):
stack_arrays((a, b), autoconvert=False)
def test_checktitles(self):
adtype = [(('a', 'A'), int), (('b', 'B'), bool), (('c', 'C'), float)]
a = ma.array([(1, 2, 3)], mask=[(0, 1, 0)], dtype=adtype)
bdtype = [(('a', 'A'), int), (('b', 'B'), bool), (('c', 'C'), float)]
b = ma.array([(4, 5, 6)], dtype=bdtype)
test = stack_arrays((a, b))
control = ma.array([(1, 2, 3), (4, 5, 6)], mask=[(0, 1, 0), (0, 0, 0)],
dtype=bdtype)
assert_equal(test, control)
assert_equal(test.mask, control.mask)
def test_subdtype(self):
z = np.array([
('A', 1), ('B', 2)
], dtype=[('A', '|S3'), ('B', float, (1,))])
zz = np.array([
('a', [10.], 100.), ('b', [20.], 200.), ('c', [30.], 300.)
], dtype=[('A', '|S3'), ('B', float, (1,)), ('C', float)])
res = stack_arrays((z, zz))
expected = ma.array(
data=[
(b'A', [1.0], 0),
(b'B', [2.0], 0),
(b'a', [10.0], 100.0),
(b'b', [20.0], 200.0),
(b'c', [30.0], 300.0)],
mask=[
(False, [False], True),
(False, [False], True),
(False, [False], False),
(False, [False], False),
(False, [False], False)
],
dtype=zz.dtype
)
assert_equal(res.dtype, expected.dtype)
assert_equal(res, expected)
assert_equal(res.mask, expected.mask)
class TestJoinBy:
def setup_method(self):
self.a = np.array(list(zip(np.arange(10), np.arange(50, 60),
np.arange(100, 110))),
dtype=[('a', int), ('b', int), ('c', int)])
self.b = np.array(list(zip(np.arange(5, 15), np.arange(65, 75),
np.arange(100, 110))),
dtype=[('a', int), ('b', int), ('d', int)])
def test_inner_join(self):
a, b = self.a, self.b
test = join_by('a', a, b, jointype='inner')
control = np.array([(5, 55, 65, 105, 100), (6, 56, 66, 106, 101),
(7, 57, 67, 107, 102), (8, 58, 68, 108, 103),
(9, 59, 69, 109, 104)],
dtype=[('a', int), ('b1', int), ('b2', int),
('c', int), ('d', int)])
assert_equal(test, control)
def test_join(self):
a, b = self.a, self.b
join_by(('a', 'b'), a, b)
np.array([(5, 55, 105, 100), (6, 56, 106, 101),
(7, 57, 107, 102), (8, 58, 108, 103),
(9, 59, 109, 104)],
dtype=[('a', int), ('b', int),
('c', int), ('d', int)])
def test_join_subdtype(self):
foo = np.array([(1,)],
dtype=[('key', int)])
bar = np.array([(1, np.array([1,2,3]))],
dtype=[('key', int), ('value', 'uint16', 3)])
res = join_by('key', foo, bar)
assert_equal(res, bar.view(ma.MaskedArray))
def test_outer_join(self):
a, b = self.a, self.b
test = join_by(('a', 'b'), a, b, 'outer')
control = ma.array([(0, 50, 100, -1), (1, 51, 101, -1),
(2, 52, 102, -1), (3, 53, 103, -1),
(4, 54, 104, -1), (5, 55, 105, -1),
(5, 65, -1, 100), (6, 56, 106, -1),
(6, 66, -1, 101), (7, 57, 107, -1),
(7, 67, -1, 102), (8, 58, 108, -1),
(8, 68, -1, 103), (9, 59, 109, -1),
(9, 69, -1, 104), (10, 70, -1, 105),
(11, 71, -1, 106), (12, 72, -1, 107),
(13, 73, -1, 108), (14, 74, -1, 109)],
mask=[(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 1, 0), (0, 0, 0, 1),
(0, 0, 1, 0), (0, 0, 0, 1),
(0, 0, 1, 0), (0, 0, 0, 1),
(0, 0, 1, 0), (0, 0, 0, 1),
(0, 0, 1, 0), (0, 0, 1, 0),
(0, 0, 1, 0), (0, 0, 1, 0),
(0, 0, 1, 0), (0, 0, 1, 0)],
dtype=[('a', int), ('b', int),
('c', int), ('d', int)])
assert_equal(test, control)
def test_leftouter_join(self):
a, b = self.a, self.b
test = join_by(('a', 'b'), a, b, 'leftouter')
control = ma.array([(0, 50, 100, -1), (1, 51, 101, -1),
(2, 52, 102, -1), (3, 53, 103, -1),
(4, 54, 104, -1), (5, 55, 105, -1),
(6, 56, 106, -1), (7, 57, 107, -1),
(8, 58, 108, -1), (9, 59, 109, -1)],
mask=[(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 0, 1), (0, 0, 0, 1),
(0, 0, 0, 1), (0, 0, 0, 1)],
dtype=[('a', int), ('b', int), ('c', int), ('d', int)])
assert_equal(test, control)
def test_different_field_order(self):
a = np.zeros(3, dtype=[('a', 'i4'), ('b', 'f4'), ('c', 'u1')])
b = np.ones(3, dtype=[('c', 'u1'), ('b', 'f4'), ('a', 'i4')])
j = join_by(['c', 'b'], a, b, jointype='inner', usemask=False)
assert_equal(j.dtype.names, ['b', 'c', 'a1', 'a2'])
def test_duplicate_keys(self):
a = np.zeros(3, dtype=[('a', 'i4'), ('b', 'f4'), ('c', 'u1')])
b = np.ones(3, dtype=[('c', 'u1'), ('b', 'f4'), ('a', 'i4')])
assert_raises(ValueError, join_by, ['a', 'b', 'b'], a, b)
def test_same_name_different_dtypes_key(self):
a_dtype = np.dtype([('key', 'S5'), ('value', '<f4')])
b_dtype = np.dtype([('key', 'S10'), ('value', '<f4')])
expected_dtype = np.dtype([
('key', 'S10'), ('value1', '<f4'), ('value2', '<f4')])
a = np.array([('Sarah', 8.0), ('John', 6.0)], dtype=a_dtype)
b = np.array([('Sarah', 10.0), ('John', 7.0)], dtype=b_dtype)
res = join_by('key', a, b)
assert_equal(res.dtype, expected_dtype)
def test_same_name_different_dtypes(self):
a_dtype = np.dtype([('key', 'S10'), ('value', '<f4')])
b_dtype = np.dtype([('key', 'S10'), ('value', '<f8')])
expected_dtype = np.dtype([
('key', '|S10'), ('value1', '<f4'), ('value2', '<f8')])
a = np.array([('Sarah', 8.0), ('John', 6.0)], dtype=a_dtype)
b = np.array([('Sarah', 10.0), ('John', 7.0)], dtype=b_dtype)
res = join_by('key', a, b)
assert_equal(res.dtype, expected_dtype)
def test_subarray_key(self):
a_dtype = np.dtype([('pos', int, 3), ('f', '<f4')])
a = np.array([([1, 1, 1], np.pi), ([1, 2, 3], 0.0)], dtype=a_dtype)
b_dtype = np.dtype([('pos', int, 3), ('g', '<f4')])
b = np.array([([1, 1, 1], 3), ([3, 2, 1], 0.0)], dtype=b_dtype)
expected_dtype = np.dtype([('pos', int, 3), ('f', '<f4'), ('g', '<f4')])
expected = np.array([([1, 1, 1], np.pi, 3)], dtype=expected_dtype)
res = join_by('pos', a, b)
assert_equal(res.dtype, expected_dtype)
assert_equal(res, expected)
def test_padded_dtype(self):
dt = np.dtype('i1,f4', align=True)
dt.names = ('k', 'v')
assert_(len(dt.descr), 3)
a = np.array([(1, 3), (3, 2)], dt)
b = np.array([(1, 1), (2, 2)], dt)
res = join_by('k', a, b)
expected_dtype = np.dtype([
('k', 'i1'), ('v1', 'f4'), ('v2', 'f4')
])
assert_equal(res.dtype, expected_dtype)
class TestJoinBy2:
@classmethod
def setup_method(cls):
cls.a = np.array(list(zip(np.arange(10), np.arange(50, 60),
np.arange(100, 110))),
dtype=[('a', int), ('b', int), ('c', int)])
cls.b = np.array(list(zip(np.arange(10), np.arange(65, 75),
np.arange(100, 110))),
dtype=[('a', int), ('b', int), ('d', int)])
def test_no_r1postfix(self):
a, b = self.a, self.b
test = join_by(
'a', a, b, r1postfix='', r2postfix='2', jointype='inner')
control = np.array([(0, 50, 65, 100, 100), (1, 51, 66, 101, 101),
(2, 52, 67, 102, 102), (3, 53, 68, 103, 103),
(4, 54, 69, 104, 104), (5, 55, 70, 105, 105),
(6, 56, 71, 106, 106), (7, 57, 72, 107, 107),
(8, 58, 73, 108, 108), (9, 59, 74, 109, 109)],
dtype=[('a', int), ('b', int), ('b2', int),
('c', int), ('d', int)])
assert_equal(test, control)
def test_no_postfix(self):
assert_raises(ValueError, join_by, 'a', self.a, self.b,
r1postfix='', r2postfix='')
def test_no_r2postfix(self):
a, b = self.a, self.b
test = join_by(
'a', a, b, r1postfix='1', r2postfix='', jointype='inner')
control = np.array([(0, 50, 65, 100, 100), (1, 51, 66, 101, 101),
(2, 52, 67, 102, 102), (3, 53, 68, 103, 103),
(4, 54, 69, 104, 104), (5, 55, 70, 105, 105),
(6, 56, 71, 106, 106), (7, 57, 72, 107, 107),
(8, 58, 73, 108, 108), (9, 59, 74, 109, 109)],
dtype=[('a', int), ('b1', int), ('b', int),
('c', int), ('d', int)])
assert_equal(test, control)
def test_two_keys_two_vars(self):
a = np.array(list(zip(np.tile([10, 11], 5), np.repeat(np.arange(5), 2),
np.arange(50, 60), np.arange(10, 20))),
dtype=[('k', int), ('a', int), ('b', int), ('c', int)])
b = np.array(list(zip(np.tile([10, 11], 5), np.repeat(np.arange(5), 2),
np.arange(65, 75), np.arange(0, 10))),
dtype=[('k', int), ('a', int), ('b', int), ('c', int)])
control = np.array([(10, 0, 50, 65, 10, 0), (11, 0, 51, 66, 11, 1),
(10, 1, 52, 67, 12, 2), (11, 1, 53, 68, 13, 3),
(10, 2, 54, 69, 14, 4), (11, 2, 55, 70, 15, 5),
(10, 3, 56, 71, 16, 6), (11, 3, 57, 72, 17, 7),
(10, 4, 58, 73, 18, 8), (11, 4, 59, 74, 19, 9)],
dtype=[('k', int), ('a', int), ('b1', int),
('b2', int), ('c1', int), ('c2', int)])
test = join_by(
['a', 'k'], a, b, r1postfix='1', r2postfix='2', jointype='inner')
assert_equal(test.dtype, control.dtype)
assert_equal(test, control)
class TestAppendFieldsObj:
"""
Test append_fields with arrays containing objects
"""
def setup_method(self):
from datetime import date
self.data = dict(obj=date(2000, 1, 1))
def test_append_to_objects(self):
obj = self.data['obj']
x = np.array([(obj, 1.), (obj, 2.)],
dtype=[('A', object), ('B', float)])
y = np.array([10, 20], dtype=int)
test = append_fields(x, 'C', data=y, usemask=False)
control = np.array([(obj, 1.0, 10), (obj, 2.0, 20)],
dtype=[('A', object), ('B', float), ('C', int)])
assert_equal(test, control)