summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/_iotools.py7
-rw-r--r--numpy/lib/arraysetops.py7
-rw-r--r--numpy/lib/financial.py10
-rw-r--r--numpy/lib/npyio.py43
-rw-r--r--numpy/lib/setup.py12
-rw-r--r--numpy/lib/shape_base.py2
-rw-r--r--numpy/lib/tests/test__iotools.py6
-rw-r--r--numpy/lib/tests/test_financial.py41
-rw-r--r--numpy/lib/tests/test_io.py95
-rw-r--r--numpy/lib/tests/test_twodim_base.py31
-rw-r--r--numpy/lib/twodim_base.py8
11 files changed, 220 insertions, 42 deletions
diff --git a/numpy/lib/_iotools.py b/numpy/lib/_iotools.py
index f2adcda10..316704b42 100644
--- a/numpy/lib/_iotools.py
+++ b/numpy/lib/_iotools.py
@@ -320,12 +320,13 @@ class NameValidator(object):
# Process the case option .....
if (case_sensitive is None) or (case_sensitive is True):
self.case_converter = lambda x: x
- elif (case_sensitive is False) or ('u' in case_sensitive):
+ elif (case_sensitive is False) or case_sensitive.startswith('u'):
self.case_converter = lambda x: x.upper()
- elif 'l' in case_sensitive:
+ elif case_sensitive.startswith('l'):
self.case_converter = lambda x: x.lower()
else:
- self.case_converter = lambda x: x
+ msg = 'unrecognized case_sensitive value %s.' % case_sensitive
+ raise ValueError(msg)
#
self.replace_space = replace_space
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py
index d3b6119f4..cb24eb24e 100644
--- a/numpy/lib/arraysetops.py
+++ b/numpy/lib/arraysetops.py
@@ -392,12 +392,13 @@ def in1d(ar1, ar2, assume_unique=False, invert=False):
else:
bool_ar = (sar[1:] == sar[:-1])
flag = np.concatenate((bool_ar, [invert]))
- indx = order.argsort(kind='mergesort')[:len(ar1)]
+ ret = np.empty(ar.shape, dtype=bool)
+ ret[order] = flag
if assume_unique:
- return flag[indx]
+ return ret[:len(ar1)]
else:
- return flag[indx][rev_idx]
+ return ret[rev_idx]
def union1d(ar1, ar2):
"""
diff --git a/numpy/lib/financial.py b/numpy/lib/financial.py
index baff8b0b6..a7e4e60b6 100644
--- a/numpy/lib/financial.py
+++ b/numpy/lib/financial.py
@@ -208,11 +208,11 @@ def pmt(rate, nper, pv, fv=0, when='end'):
"""
when = _convert_when(when)
(rate, nper, pv, fv, when) = map(np.asarray, [rate, nper, pv, fv, when])
- temp = (1+rate)**nper
- miter = np.broadcast(rate, nper, pv, fv, when)
- zer = np.zeros(miter.shape)
- fact = np.where(rate == zer, nper + zer,
- (1 + rate*when)*(temp - 1)/rate + zer)
+ temp = (1 + rate)**nper
+ mask = (rate == 0.0)
+ np.copyto(rate, 1.0, where=mask)
+ z = np.zeros(np.broadcast(rate, nper, pv, fv, when).shape)
+ fact = np.where(mask != z, nper + z, (1 + rate*when)*(temp - 1)/rate + z)
return -(fv + pv*temp) / fact
def nper(rate, pmt, pv, fv=0, when='end'):
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index 9d539d6ac..0632ba1f8 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -621,6 +621,13 @@ def _savez(file, args, kwds, compress):
def _getconv(dtype):
""" Find the correct dtype converter. Adapted from matplotlib """
+
+ def floatconv(x):
+ x.lower()
+ if b'0x' in x:
+ return float.fromhex(asstr(x))
+ return float(x)
+
typ = dtype.type
if issubclass(typ, np.bool_):
return lambda x: bool(int(x))
@@ -631,7 +638,7 @@ def _getconv(dtype):
if issubclass(typ, np.integer):
return lambda x: int(float(x))
elif issubclass(typ, np.floating):
- return float
+ return floatconv
elif issubclass(typ, np.complex):
return complex
elif issubclass(typ, np.bytes_):
@@ -706,6 +713,10 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
`genfromtxt` function provides more sophisticated handling of, e.g.,
lines with missing values.
+ .. versionadded:: 1.10.0
+ The strings produced by the Python float.hex method can be used as
+ input for floats.
+
Examples
--------
>>> from StringIO import StringIO # StringIO behaves like a file object
@@ -1204,7 +1215,8 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
usecols=None, names=None,
excludelist=None, deletechars=None, replace_space='_',
autostrip=False, case_sensitive=True, defaultfmt="f%i",
- unpack=None, usemask=False, loose=True, invalid_raise=True):
+ unpack=None, usemask=False, loose=True, invalid_raise=True,
+ max_rows=None):
"""
Load data from a text file, with missing values handled as specified.
@@ -1285,6 +1297,12 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
If True, an exception is raised if an inconsistency is detected in the
number of columns.
If False, a warning is emitted and the offending lines are skipped.
+ max_rows : int, optional
+ The maximum number of rows to read. Must not be used with skip_footer
+ at the same time. If given, the value must be at least 1. Default is
+ to read the entire file.
+
+ .. versionadded:: 1.10.0
Returns
-------
@@ -1353,6 +1371,14 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
dtype=[('intvar', '<i8'), ('fltvar', '<f8'), ('strvar', '|S5')])
"""
+ if max_rows is not None:
+ if skip_footer:
+ raise ValueError(
+ "The keywords 'skip_footer' and 'max_rows' can not be "
+ "specified at the same time.")
+ if max_rows < 1:
+ raise ValueError("'max_rows' must be at least 1.")
+
# Py3 data conversions to bytes, for convenience
if comments is not None:
comments = asbytes(comments)
@@ -1451,7 +1477,11 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
names = validate_names(names)
# Get the dtype
if dtype is not None:
- dtype = easy_dtype(dtype, defaultfmt=defaultfmt, names=names)
+ dtype = easy_dtype(dtype, defaultfmt=defaultfmt, names=names,
+ excludelist=excludelist,
+ deletechars=deletechars,
+ case_sensitive=case_sensitive,
+ replace_space=replace_space)
# Make sure the names is a list (for 2.5)
if names is not None:
names = list(names)
@@ -1647,8 +1677,8 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
# Skip an empty line
if nbvalues == 0:
continue
- # Select only the columns we need
if usecols:
+ # Select only the columns we need
try:
values = [values[_] for _ in usecols]
except IndexError:
@@ -1661,7 +1691,10 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
append_to_rows(tuple(values))
if usemask:
append_to_masks(tuple([v.strip() in m
- for (v, m) in zip(values, missing_values)]))
+ for (v, m) in zip(values,
+ missing_values)]))
+ if len(rows) == max_rows:
+ break
if own_fhd:
fhd.close()
diff --git a/numpy/lib/setup.py b/numpy/lib/setup.py
new file mode 100644
index 000000000..d342410b8
--- /dev/null
+++ b/numpy/lib/setup.py
@@ -0,0 +1,12 @@
+from __future__ import division, print_function
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+
+ config = Configuration('lib', parent_package, top_path)
+ config.add_data_dir('tests')
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py
index 70fa3ab03..2d18c5bc8 100644
--- a/numpy/lib/shape_base.py
+++ b/numpy/lib/shape_base.py
@@ -711,7 +711,7 @@ def kron(a, b):
Notes
-----
- The function assumes that the number of dimenensions of `a` and `b`
+ The function assumes that the number of dimensions of `a` and `b`
are the same, if necessary prepending the smallest with ones.
If `a.shape = (r0,r1,..,rN)` and `b.shape = (s0,s1,...,sN)`,
the Kronecker product has shape `(r0*s0, r1*s1, ..., rN*SN)`.
diff --git a/numpy/lib/tests/test__iotools.py b/numpy/lib/tests/test__iotools.py
index 92ca1c973..060f815d5 100644
--- a/numpy/lib/tests/test__iotools.py
+++ b/numpy/lib/tests/test__iotools.py
@@ -7,7 +7,8 @@ from datetime import date
import numpy as np
from numpy.compat import asbytes, asbytes_nested
from numpy.testing import (
- run_module_suite, TestCase, assert_, assert_equal, assert_allclose
+ run_module_suite, TestCase, assert_, assert_equal, assert_allclose,
+ assert_raises
)
from numpy.lib._iotools import (
LineSplitter, NameValidator, StringConverter,
@@ -93,6 +94,9 @@ class TestNameValidator(TestCase):
test = NameValidator(case_sensitive='lower').validate(names)
assert_equal(test, ['a', 'a_1', 'b', 'c'])
+ # check exceptions
+ assert_raises(ValueError, NameValidator, case_sensitive='foobar')
+
def test_excludelist(self):
"Test excludelist"
names = ['dates', 'data', 'Other Data', 'mask']
diff --git a/numpy/lib/tests/test_financial.py b/numpy/lib/tests/test_financial.py
index a4b9cfe2e..baa785424 100644
--- a/numpy/lib/tests/test_financial.py
+++ b/numpy/lib/tests/test_financial.py
@@ -2,7 +2,8 @@ from __future__ import division, absolute_import, print_function
import numpy as np
from numpy.testing import (
- run_module_suite, TestCase, assert_, assert_almost_equal
+ run_module_suite, TestCase, assert_, assert_almost_equal,
+ assert_allclose
)
@@ -13,35 +14,37 @@ class TestFinancial(TestCase):
def test_irr(self):
v = [-150000, 15000, 25000, 35000, 45000, 60000]
- assert_almost_equal(np.irr(v),
- 0.0524, 2)
+ assert_almost_equal(np.irr(v), 0.0524, 2)
v = [-100, 0, 0, 74]
- assert_almost_equal(np.irr(v),
- -0.0955, 2)
+ assert_almost_equal(np.irr(v), -0.0955, 2)
v = [-100, 39, 59, 55, 20]
- assert_almost_equal(np.irr(v),
- 0.28095, 2)
+ assert_almost_equal(np.irr(v), 0.28095, 2)
v = [-100, 100, 0, -7]
- assert_almost_equal(np.irr(v),
- -0.0833, 2)
+ assert_almost_equal(np.irr(v), -0.0833, 2)
v = [-100, 100, 0, 7]
- assert_almost_equal(np.irr(v),
- 0.06206, 2)
+ assert_almost_equal(np.irr(v), 0.06206, 2)
v = [-5, 10.5, 1, -8, 1]
- assert_almost_equal(np.irr(v),
- 0.0886, 2)
+ assert_almost_equal(np.irr(v), 0.0886, 2)
def test_pv(self):
- assert_almost_equal(np.pv(0.07, 20, 12000, 0),
- -127128.17, 2)
+ assert_almost_equal(np.pv(0.07, 20, 12000, 0), -127128.17, 2)
def test_fv(self):
- assert_almost_equal(np.fv(0.075, 20, -2000, 0, 0),
- 86609.36, 2)
+ assert_almost_equal(np.fv(0.075, 20, -2000, 0, 0), 86609.36, 2)
def test_pmt(self):
- assert_almost_equal(np.pmt(0.08/12, 5*12, 15000),
- -304.146, 3)
+ res = np.pmt(0.08/12, 5*12, 15000)
+ tgt = -304.145914
+ assert_allclose(res, tgt)
+ # Test the edge case where rate == 0.0
+ res = np.pmt(0.0, 5*12, 15000)
+ tgt = -250.0
+ assert_allclose(res, tgt)
+ # Test the case where we use broadcast and
+ # the arguments passed in are arrays.
+ res = np.pmt([[0.0, 0.8],[0.3, 0.8]],[12, 3],[2000, 20000])
+ tgt = np.array([[-166.66667, -19311.258],[-626.90814, -19311.258]])
+ assert_allclose(res, tgt)
def test_ppmt(self):
np.round(np.ppmt(0.1/12, 1, 60, 55000), 2) == 710.25
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
index 81bddfadd..7054ab1fe 100644
--- a/numpy/lib/tests/test_io.py
+++ b/numpy/lib/tests/test_io.py
@@ -694,6 +694,19 @@ class TestLoadTxt(TestCase):
res = np.loadtxt(c, dtype=np.int64)
assert_equal(res, tgt)
+ def test_from_float_hex(self):
+ # IEEE doubles and floats only, otherwise the float32
+ # conversion may fail.
+ tgt = np.logspace(-10, 10, 5).astype(np.float32)
+ tgt = np.hstack((tgt, -tgt)).astype(np.float)
+ inp = '\n'.join(map(float.hex, tgt))
+ c = TextIO()
+ c.write(inp)
+ for dt in [np.float, np.float32]:
+ c.seek(0)
+ res = np.loadtxt(c, dtype=dt)
+ assert_equal(res, tgt, err_msg="%s" % dt)
+
def test_universal_newline(self):
f, name = mkstemp()
os.write(f, b'1 21\r3 42\r')
@@ -1107,13 +1120,13 @@ M 33 21.99
def test_dtype_with_converters_and_usecols(self):
dstr = "1,5,-1,1:1\n2,8,-1,1:n\n3,3,-2,m:n\n"
dmap = {'1:1':0, '1:n':1, 'm:1':2, 'm:n':3}
- dtyp = [('E1','i4'),('E2','i4'),('E3','i2'),('N', 'i1')]
+ dtyp = [('e1','i4'),('e2','i4'),('e3','i2'),('n', 'i1')]
conv = {0: int, 1: int, 2: int, 3: lambda r: dmap[r.decode()]}
test = np.recfromcsv(TextIO(dstr,), dtype=dtyp, delimiter=',',
names=None, converters=conv)
control = np.rec.array([[1,5,-1,0], [2,8,-1,1], [3,3,-2,3]], dtype=dtyp)
assert_equal(test, control)
- dtyp = [('E1','i4'),('E2','i4'),('N', 'i1')]
+ dtyp = [('e1','i4'),('e2','i4'),('n', 'i1')]
test = np.recfromcsv(TextIO(dstr,), dtype=dtyp, delimiter=',',
usecols=(0,1,3), names=None, converters=conv)
control = np.rec.array([[1,5,0], [2,8,1], [3,3,3]], dtype=dtyp)
@@ -1514,6 +1527,30 @@ M 33 21.99
ctrl = np.array((1, 2, 3.14), dtype=ctrl_dtype)
assert_equal(test, ctrl)
+ def test_replace_space_known_dtype(self):
+ "Test the 'replace_space' (and related) options when dtype != None"
+ txt = "A.A, B (B), C:C\n1, 2, 3"
+ # Test default: replace ' ' by '_' and delete non-alphanum chars
+ test = np.genfromtxt(TextIO(txt),
+ delimiter=",", names=True, dtype=int)
+ ctrl_dtype = [("AA", int), ("B_B", int), ("CC", int)]
+ ctrl = np.array((1, 2, 3), dtype=ctrl_dtype)
+ assert_equal(test, ctrl)
+ # Test: no replace, no delete
+ test = np.genfromtxt(TextIO(txt),
+ delimiter=",", names=True, dtype=int,
+ replace_space='', deletechars='')
+ ctrl_dtype = [("A.A", int), ("B (B)", int), ("C:C", int)]
+ ctrl = np.array((1, 2, 3), dtype=ctrl_dtype)
+ assert_equal(test, ctrl)
+ # Test: no delete (spaces are replaced by _)
+ test = np.genfromtxt(TextIO(txt),
+ delimiter=",", names=True, dtype=int,
+ deletechars='')
+ ctrl_dtype = [("A.A", int), ("B_(B)", int), ("C:C", int)]
+ ctrl = np.array((1, 2, 3), dtype=ctrl_dtype)
+ assert_equal(test, ctrl)
+
def test_incomplete_names(self):
"Test w/ incomplete names"
data = "A,,C\n0,1,2\n3,4,5"
@@ -1641,6 +1678,60 @@ M 33 21.99
self.assertTrue(isinstance(test, np.recarray))
assert_equal(test, control)
+ def test_max_rows(self):
+ # Test the `max_rows` keyword argument.
+ data = '1 2\n3 4\n5 6\n7 8\n9 10\n'
+ txt = TextIO(data)
+ a1 = np.genfromtxt(txt, max_rows=3)
+ a2 = np.genfromtxt(txt)
+ assert_equal(a1, [[1, 2], [3, 4], [5, 6]])
+ assert_equal(a2, [[7, 8], [9, 10]])
+
+ # max_rows must be at least 1.
+ assert_raises(ValueError, np.genfromtxt, TextIO(data), max_rows=0)
+
+ # An input with several invalid rows.
+ data = '1 1\n2 2\n0 \n3 3\n4 4\n5 \n6 \n7 \n'
+
+ test = np.genfromtxt(TextIO(data), max_rows=2)
+ control = np.array([[1., 1.], [2., 2.]])
+ assert_equal(test, control)
+
+ # Test keywords conflict
+ assert_raises(ValueError, np.genfromtxt, TextIO(data), skip_footer=1,
+ max_rows=4)
+
+ # Test with invalid value
+ assert_raises(ValueError, np.genfromtxt, TextIO(data), max_rows=4)
+
+ # Test with invalid not raise
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore")
+
+ test = np.genfromtxt(TextIO(data), max_rows=4, invalid_raise=False)
+ control = np.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
+ assert_equal(test, control)
+
+ test = np.genfromtxt(TextIO(data), max_rows=5, invalid_raise=False)
+ control = np.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
+ assert_equal(test, control)
+
+ # Structured array with field names.
+ data = 'a b\n#c d\n1 1\n2 2\n#0 \n3 3\n4 4\n5 5\n'
+
+ # Test with header, names and comments
+ txt = TextIO(data)
+ test = np.genfromtxt(txt, skip_header=1, max_rows=3, names=True)
+ control = np.array([(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)],
+ dtype=[('c', '<f8'), ('d', '<f8')])
+ assert_equal(test, control)
+ # To continue reading the same "file", don't use skip_header or
+ # names, and use the previously determined dtype.
+ test = np.genfromtxt(txt, max_rows=None, dtype=test.dtype)
+ control = np.array([(4.0, 4.0), (5.0, 5.0)],
+ dtype=[('c', '<f8'), ('d', '<f8')])
+ assert_equal(test, control)
+
def test_gft_using_filename(self):
# Test that we can load data from a filename as well as a file object
wanted = np.arange(6).reshape((2, 3))
diff --git a/numpy/lib/tests/test_twodim_base.py b/numpy/lib/tests/test_twodim_base.py
index 739061a5d..b65a8df97 100644
--- a/numpy/lib/tests/test_twodim_base.py
+++ b/numpy/lib/tests/test_twodim_base.py
@@ -265,6 +265,37 @@ class TestHistogram2d(TestCase):
a, edge1, edge2 = histogram2d([], [], bins=4)
assert_array_max_ulp(a, np.zeros((4, 4)))
+ def test_binparameter_combination(self):
+ x = array(
+ [0, 0.09207008, 0.64575234, 0.12875982, 0.47390599,
+ 0.59944483, 1])
+ y = array(
+ [0, 0.14344267, 0.48988575, 0.30558665, 0.44700682,
+ 0.15886423, 1])
+ edges = (0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1)
+ H, xe, ye = histogram2d(x, y, (edges, 4))
+ answer = array(
+ [[ 2., 0., 0., 0.],
+ [ 0., 1., 0., 0.],
+ [ 0., 0., 0., 0.],
+ [ 0., 0., 0., 0.],
+ [ 0., 1., 0., 0.],
+ [ 1., 0., 0., 0.],
+ [ 0., 1., 0., 0.],
+ [ 0., 0., 0., 0.],
+ [ 0., 0., 0., 0.],
+ [ 0., 0., 0., 1.]])
+ assert_array_equal(H, answer)
+ assert_array_equal(ye, array([0., 0.25, 0.5, 0.75, 1]))
+ H, xe, ye = histogram2d(x, y, (4, edges))
+ answer = array(
+ [[ 1., 1., 0., 1., 0., 0., 0., 0., 0., 0.],
+ [ 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
+ [ 0., 1., 0., 0., 1., 0., 0., 0., 0., 0.],
+ [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
+ assert_array_equal(H, answer)
+ assert_array_equal(xe, array([0., 0.25, 0.5, 0.75, 1]))
+
class TestTri(TestCase):
def test_dtype(self):
diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py
index 24dc3cced..464ffd914 100644
--- a/numpy/lib/twodim_base.py
+++ b/numpy/lib/twodim_base.py
@@ -589,16 +589,18 @@ def histogram2d(x, y, bins=10, range=None, normed=False, weights=None):
y : array_like, shape (N,)
An array containing the y coordinates of the points to be
histogrammed.
- bins : int or [int, int] or array_like or [array, array], optional
+ bins : int or array_like or [int, int] or [array, array], optional
The bin specification:
* If int, the number of bins for the two dimensions (nx=ny=bins).
- * If [int, int], the number of bins in each dimension
- (nx, ny = bins).
* If array_like, the bin edges for the two dimensions
(x_edges=y_edges=bins).
+ * If [int, int], the number of bins in each dimension
+ (nx, ny = bins).
* If [array, array], the bin edges in each dimension
(x_edges, y_edges = bins).
+ * A combination [int, array] or [array, int], where int
+ is the number of bins and array is the bin edges.
range : array_like, shape(2,2), optional
The leftmost and rightmost edges of the bins along each dimension