diff options
-rw-r--r-- | numpy/polynomial/chebyshev.py | 39 | ||||
-rw-r--r-- | numpy/polynomial/hermite.py | 39 | ||||
-rw-r--r-- | numpy/polynomial/hermite_e.py | 39 | ||||
-rw-r--r-- | numpy/polynomial/laguerre.py | 39 | ||||
-rw-r--r-- | numpy/polynomial/legendre.py | 39 | ||||
-rw-r--r-- | numpy/polynomial/polynomial.py | 64 | ||||
-rw-r--r-- | numpy/polynomial/polytemplate.py | 5 |
7 files changed, 184 insertions, 80 deletions
diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py index d66ec5ef3..96dc983ba 100644 --- a/numpy/polynomial/chebyshev.py +++ b/numpy/polynomial/chebyshev.py @@ -1444,7 +1444,10 @@ def chebvander(x, deg) : raise ValueError("deg must be non-negative") x = np.array(x, copy=0, ndmin=1) + 0.0 - v = np.empty((ideg + 1,) + x.shape, dtype=x.dtype) + dims = (ideg + 1,) + x.shape + mask = x.flags.maskna + dtyp = x.dtype + v = np.empty(dims, dtype=dtyp, maskna=mask) # Use forward recursion to generate the entries. v[0] = x*0 + 1 if ideg > 0 : @@ -1590,6 +1593,11 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None): where `n` is `deg`. + Since numpy version 1.7.0, chebfit also supports NA. If any of the + elements of `x`, `y`, or `w` are NA, then the corresponding rows of the + linear least squares problem (see Notes) are set to 0. If `y` is 2-D, + then an NA in any row of `y` invalidates that whole row. + Parameters ---------- x : array_like, shape (M,) @@ -1702,30 +1710,37 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None): if len(x) != len(y): raise TypeError("expected x and y to have same length") - # set up the least squares matrices - lhs = chebvander(x, deg) - rhs = y + # set up the least squares matrices in transposed form + lhs = chebvander(x, deg).T + rhs = y.T if w is not None: w = np.asarray(w) + 0.0 if w.ndim != 1: raise TypeError("expected 1D vector for w") if len(x) != len(w): raise TypeError("expected x and w to have same length") - # apply weights - if rhs.ndim == 2: - lhs *= w[:, np.newaxis] - rhs *= w[:, np.newaxis] + # apply weights. Don't use inplace operations as they + # can cause problems with NA. + lhs = lhs * w + rhs = rhs * w + + # deal with NA. Note that polyvander propagates NA from x + # into all columns, that is rows for transposed form. + if lhs.flags.maskna or rhs.flags.maskna: + if rhs.ndim == 1: + mask = np.isna(lhs[0]) | np.isna(rhs) else: - lhs *= w[:, np.newaxis] - rhs *= w + mask = np.isna(lhs[0]) | np.isna(rhs).any(0) + np.copyto(lhs, 0, where=mask) + np.copyto(rhs, 0, where=mask) # set rcond if rcond is None : rcond = len(x)*np.finfo(x.dtype).eps # scale the design matrix and solve the least squares equation - scl = np.sqrt((lhs*lhs).sum(0)) - c, resids, rank, s = la.lstsq(lhs/scl, rhs, rcond) + scl = np.sqrt((lhs*lhs).sum(1)) + c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond) c = (c.T/scl).T # warn on rank reduction diff --git a/numpy/polynomial/hermite.py b/numpy/polynomial/hermite.py index 8781ff1e2..c0f8688b0 100644 --- a/numpy/polynomial/hermite.py +++ b/numpy/polynomial/hermite.py @@ -1217,7 +1217,10 @@ def hermvander(x, deg) : raise ValueError("deg must be non-negative") x = np.array(x, copy=0, ndmin=1) + 0.0 - v = np.empty((ideg + 1,) + x.shape, dtype=x.dtype) + dims = (ideg + 1,) + x.shape + mask = x.flags.maskna + dtyp = x.dtype + v = np.empty(dims, dtype=dtyp, maskna=mask) v[0] = x*0 + 1 if ideg > 0 : x2 = x*2 @@ -1362,6 +1365,11 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None): where `n` is `deg`. + Since numpy version 1.7.0, hermfit also supports NA. If any of the + elements of `x`, `y`, or `w` are NA, then the corresponding rows of the + linear least squares problem (see Notes) are set to 0. If `y` is 2-D, + then an NA in any row of `y` invalidates that whole row. + Parameters ---------- x : array_like, shape (M,) @@ -1479,30 +1487,37 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None): if len(x) != len(y): raise TypeError("expected x and y to have same length") - # set up the least squares matrices - lhs = hermvander(x, deg) - rhs = y + # set up the least squares matrices in transposed form + lhs = hermvander(x, deg).T + rhs = y.T if w is not None: w = np.asarray(w) + 0.0 if w.ndim != 1: raise TypeError("expected 1D vector for w") if len(x) != len(w): raise TypeError("expected x and w to have same length") - # apply weights - if rhs.ndim == 2: - lhs *= w[:, np.newaxis] - rhs *= w[:, np.newaxis] + # apply weights. Don't use inplace operations as they + # can cause problems with NA. + lhs = lhs * w + rhs = rhs * w + + # deal with NA. Note that polyvander propagates NA from x + # into all columns, that is rows for transposed form. + if lhs.flags.maskna or rhs.flags.maskna: + if rhs.ndim == 1: + mask = np.isna(lhs[0]) | np.isna(rhs) else: - lhs *= w[:, np.newaxis] - rhs *= w + mask = np.isna(lhs[0]) | np.isna(rhs).any(0) + np.copyto(lhs, 0, where=mask) + np.copyto(rhs, 0, where=mask) # set rcond if rcond is None : rcond = len(x)*np.finfo(x.dtype).eps # scale the design matrix and solve the least squares equation - scl = np.sqrt((lhs*lhs).sum(0)) - c, resids, rank, s = la.lstsq(lhs/scl, rhs, rcond) + scl = np.sqrt((lhs*lhs).sum(1)) + c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond) c = (c.T/scl).T # warn on rank reduction diff --git a/numpy/polynomial/hermite_e.py b/numpy/polynomial/hermite_e.py index 7a42d48a3..b81681a82 100644 --- a/numpy/polynomial/hermite_e.py +++ b/numpy/polynomial/hermite_e.py @@ -1214,7 +1214,10 @@ def hermevander(x, deg) : raise ValueError("deg must be non-negative") x = np.array(x, copy=0, ndmin=1) + 0.0 - v = np.empty((ideg + 1,) + x.shape, dtype=x.dtype) + dims = (ideg + 1,) + x.shape + mask = x.flags.maskna + dtyp = x.dtype + v = np.empty(dims, dtype=dtyp, maskna=mask) v[0] = x*0 + 1 if ideg > 0 : v[1] = x @@ -1358,6 +1361,11 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None): where `n` is `deg`. + Since numpy version 1.7.0, hermefit also supports NA. If any of the + elements of `x`, `y`, or `w` are NA, then the corresponding rows of the + linear least squares problem (see Notes) are set to 0. If `y` is 2-D, + then an NA in any row of `y` invalidates that whole row. + Parameters ---------- x : array_like, shape (M,) @@ -1475,30 +1483,37 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None): if len(x) != len(y): raise TypeError("expected x and y to have same length") - # set up the least squares matrices - lhs = hermevander(x, deg) - rhs = y + # set up the least squares matrices in transposed form + lhs = hermevander(x, deg).T + rhs = y.T if w is not None: w = np.asarray(w) + 0.0 if w.ndim != 1: raise TypeError("expected 1D vector for w") if len(x) != len(w): raise TypeError("expected x and w to have same length") - # apply weights - if rhs.ndim == 2: - lhs *= w[:, np.newaxis] - rhs *= w[:, np.newaxis] + # apply weights. Don't use inplace operations as they + # can cause problems with NA. + lhs = lhs * w + rhs = rhs * w + + # deal with NA. Note that polyvander propagates NA from x + # into all columns, that is rows for transposed form. + if lhs.flags.maskna or rhs.flags.maskna: + if rhs.ndim == 1: + mask = np.isna(lhs[0]) | np.isna(rhs) else: - lhs *= w[:, np.newaxis] - rhs *= w + mask = np.isna(lhs[0]) | np.isna(rhs).any(0) + np.copyto(lhs, 0, where=mask) + np.copyto(rhs, 0, where=mask) # set rcond if rcond is None : rcond = len(x)*np.finfo(x.dtype).eps # scale the design matrix and solve the least squares equation - scl = np.sqrt((lhs*lhs).sum(0)) - c, resids, rank, s = la.lstsq(lhs/scl, rhs, rcond) + scl = np.sqrt((lhs*lhs).sum(1)) + c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond) c = (c.T/scl).T # warn on rank reduction diff --git a/numpy/polynomial/laguerre.py b/numpy/polynomial/laguerre.py index 710b480d9..40a81414c 100644 --- a/numpy/polynomial/laguerre.py +++ b/numpy/polynomial/laguerre.py @@ -1217,7 +1217,10 @@ def lagvander(x, deg) : raise ValueError("deg must be non-negative") x = np.array(x, copy=0, ndmin=1) + 0.0 - v = np.empty((ideg + 1,) + x.shape, dtype=x.dtype) + dims = (ideg + 1,) + x.shape + mask = x.flags.maskna + dtyp = x.dtype + v = np.empty(dims, dtype=dtyp, maskna=mask) v[0] = x*0 + 1 if ideg > 0 : v[1] = 1 - x @@ -1361,6 +1364,11 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None): where `n` is `deg`. + Since numpy version 1.7.0, lagfit also supports NA. If any of the + elements of `x`, `y`, or `w` are NA, then the corresponding rows of the + linear least squares problem (see Notes) are set to 0. If `y` is 2-D, + then an NA in any row of `y` invalidates that whole row. + Parameters ---------- x : array_like, shape (M,) @@ -1478,30 +1486,37 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None): if len(x) != len(y): raise TypeError("expected x and y to have same length") - # set up the least squares matrices - lhs = lagvander(x, deg) - rhs = y + # set up the least squares matrices in transposed form + lhs = lagvander(x, deg).T + rhs = y.T if w is not None: w = np.asarray(w) + 0.0 if w.ndim != 1: raise TypeError("expected 1D vector for w") if len(x) != len(w): raise TypeError("expected x and w to have same length") - # apply weights - if rhs.ndim == 2: - lhs *= w[:, np.newaxis] - rhs *= w[:, np.newaxis] + # apply weights. Don't use inplace operations as they + # can cause problems with NA. + lhs = lhs * w + rhs = rhs * w + + # deal with NA. Note that polyvander propagates NA from x + # into all columns, that is rows for transposed form. + if lhs.flags.maskna or rhs.flags.maskna: + if rhs.ndim == 1: + mask = np.isna(lhs[0]) | np.isna(rhs) else: - lhs *= w[:, np.newaxis] - rhs *= w + mask = np.isna(lhs[0]) | np.isna(rhs).any(0) + np.copyto(lhs, 0, where=mask) + np.copyto(rhs, 0, where=mask) # set rcond if rcond is None : rcond = len(x)*np.finfo(x.dtype).eps # scale the design matrix and solve the least squares equation - scl = np.sqrt((lhs*lhs).sum(0)) - c, resids, rank, s = la.lstsq(lhs/scl, rhs, rcond) + scl = np.sqrt((lhs*lhs).sum(1)) + c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond) c = (c.T/scl).T # warn on rank reduction diff --git a/numpy/polynomial/legendre.py b/numpy/polynomial/legendre.py index bc9b5c2e6..97c387359 100644 --- a/numpy/polynomial/legendre.py +++ b/numpy/polynomial/legendre.py @@ -1245,7 +1245,10 @@ def legvander(x, deg) : raise ValueError("deg must be non-negative") x = np.array(x, copy=0, ndmin=1) + 0.0 - v = np.empty((ideg + 1,) + x.shape, dtype=x.dtype) + dims = (ideg + 1,) + x.shape + mask = x.flags.maskna + dtyp = x.dtype + v = np.empty(dims, dtype=dtyp, maskna=mask) # Use forward recursion to generate the entries. This is not as accurate # as reverse recursion in this application but it is more efficient. v[0] = x*0 + 1 @@ -1391,6 +1394,11 @@ def legfit(x, y, deg, rcond=None, full=False, w=None): where `n` is `deg`. + Since numpy version 1.7.0, legfit also supports NA. If any of the + elements of `x`, `y`, or `w` are NA, then the corresponding rows of the + linear least squares problem (see Notes) are set to 0. If `y` is 2-D, + then an NA in any row of `y` invalidates that whole row. + Parameters ---------- x : array_like, shape (M,) @@ -1503,30 +1511,37 @@ def legfit(x, y, deg, rcond=None, full=False, w=None): if len(x) != len(y): raise TypeError("expected x and y to have same length") - # set up the least squares matrices - lhs = legvander(x, deg) - rhs = y + # set up the least squares matrices in transposed form + lhs = legvander(x, deg).T + rhs = y.T if w is not None: w = np.asarray(w) + 0.0 if w.ndim != 1: raise TypeError("expected 1D vector for w") if len(x) != len(w): raise TypeError("expected x and w to have same length") - # apply weights - if rhs.ndim == 2: - lhs *= w[:, np.newaxis] - rhs *= w[:, np.newaxis] + # apply weights. Don't use inplace operations as they + # can cause problems with NA. + lhs = lhs * w + rhs = rhs * w + + # deal with NA. Note that polyvander propagates NA from x + # into all columns, that is rows for transposed form. + if lhs.flags.maskna or rhs.flags.maskna: + if rhs.ndim == 1: + mask = np.isna(lhs[0]) | np.isna(rhs) else: - lhs *= w[:, np.newaxis] - rhs *= w + mask = np.isna(lhs[0]) | np.isna(rhs).any(0) + np.copyto(lhs, 0, where=mask) + np.copyto(rhs, 0, where=mask) # set rcond if rcond is None : rcond = len(x)*np.finfo(x.dtype).eps # scale the design matrix and solve the least squares equation - scl = np.sqrt((lhs*lhs).sum(0)) - c, resids, rank, s = la.lstsq(lhs/scl, rhs, rcond) + scl = np.sqrt((lhs*lhs).sum(1)) + c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond) c = (c.T/scl).T # warn on rank reduction diff --git a/numpy/polynomial/polynomial.py b/numpy/polynomial/polynomial.py index b7c0ae774..4f6aad009 100644 --- a/numpy/polynomial/polynomial.py +++ b/numpy/polynomial/polynomial.py @@ -517,8 +517,13 @@ def polyder(c, m=1, scl=1, axis=0): """ c = np.array(c, ndmin=1, copy=1) + if c.flags.maskna and isna(c).any(): + raise ValueError("Coefficient array contains NA") if c.dtype.char in '?bBhHiIlLqQpP': - c = c.astype(np.double) + # astype fails with NA + c = c + 0.0 + mna = c.flags.maskna + cdt = c.dtype cnt, iaxis = [int(t) for t in [m, axis]] if cnt != m: @@ -543,7 +548,7 @@ def polyder(c, m=1, scl=1, axis=0): for i in range(cnt): n = n - 1 c *= scl - der = np.empty((n,) + c.shape[1:], dtype=c.dtype) + der = np.empty((n,) + c.shape[1:], dtype=cdt, maskna=mna) for j in range(n, 0, -1): der[j - 1] = j*c[j] c = der @@ -629,8 +634,13 @@ def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0): """ c = np.array(c, ndmin=1, copy=1) - if c.dtype.char in '?bBhHiIlLqQpP': - c = c.astype(np.double) + if c.flags.maskna and isna(c).any(): + raise ValueError("Coefficient array contains NA") + elif c.dtype.char in '?bBhHiIlLqQpP': + # astype doesn't preserve mask attribute. + c = c + 0.0 + mna = c.flags.maskna + cdt = c.dtype if not np.iterable(k): k = [k] cnt, iaxis = [int(t) for t in [m, axis]] @@ -660,7 +670,7 @@ def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0): if n == 1 and np.all(c[0] == 0): c[0] += k[i] else: - tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype) + tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt, maskna=mna) tmp[0] = c[0]*0 tmp[1] = c[0] for j in range(1, n): @@ -753,8 +763,11 @@ def polyval(x, c, tensor=True): """ c = np.array(c, ndmin=1, copy=0) + if c.flags.maskna and isna(c).any(): + raise ValueError("Coefficient array contains NA") if c.dtype.char in '?bBhHiIlLqQpP': - c = c.astype(np.double) + # astype fails with NA + c = c + 0.0 if isinstance(x, (tuple, list)): x = np.asarray(x) if isinstance(x, np.ndarray) and tensor: @@ -1041,7 +1054,10 @@ def polyvander(x, deg) : raise ValueError("deg must be non-negative") x = np.array(x, copy=0, ndmin=1) + 0.0 - v = np.empty((ideg + 1,) + x.shape, dtype=x.dtype) + dims = (ideg + 1,) + x.shape + mask = x.flags.maskna + dtyp = x.dtype + v = np.empty(dims, dtype=dtyp, maskna=mask) v[0] = x*0 + 1 if ideg > 0 : v[1] = x @@ -1184,6 +1200,11 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None): where `n` is `deg`. + Since numpy version 1.7.0, polyfit also supports NA. If any of the + elements of `x`, `y`, or `w` are NA, then the corresponding rows of the + linear least squares problem (see Notes) are set to 0. If `y` is 2-D, + then an NA in any row of `y` invalidates that whole row. + Parameters ---------- x : array_like, shape (`M`,) @@ -1320,30 +1341,37 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None): if len(x) != len(y): raise TypeError("expected x and y to have same length") - # set up the least squares matrices - lhs = polyvander(x, deg) - rhs = y + # set up the least squares matrices in transposed form + lhs = polyvander(x, deg).T + rhs = y.T if w is not None: w = np.asarray(w) + 0.0 if w.ndim != 1: raise TypeError("expected 1D vector for w") if len(x) != len(w): raise TypeError("expected x and w to have same length") - # apply weights - if rhs.ndim == 2: - lhs *= w[:, np.newaxis] - rhs *= w[:, np.newaxis] + # apply weights. Don't use inplace operations as they + # can cause problems with NA. + lhs = lhs * w + rhs = rhs * w + + # deal with NA. Note that polyvander propagates NA from x + # into all columns, that is rows for transposed form. + if lhs.flags.maskna or rhs.flags.maskna: + if rhs.ndim == 1: + mask = np.isna(lhs[0]) | np.isna(rhs) else: - lhs *= w[:, np.newaxis] - rhs *= w + mask = np.isna(lhs[0]) | np.isna(rhs).any(0) + np.copyto(lhs, 0, where=mask) + np.copyto(rhs, 0, where=mask) # set rcond if rcond is None : rcond = len(x)*np.finfo(x.dtype).eps # scale the design matrix and solve the least squares equation - scl = np.sqrt((lhs*lhs).sum(0)) - c, resids, rank, s = la.lstsq(lhs/scl, rhs, rcond) + scl = np.sqrt((lhs*lhs).sum(1)) + c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond) c = (c.T/scl).T # warn on rank reduction diff --git a/numpy/polynomial/polytemplate.py b/numpy/polynomial/polytemplate.py index 2e948eecc..659f773e8 100644 --- a/numpy/polynomial/polytemplate.py +++ b/numpy/polynomial/polytemplate.py @@ -720,8 +720,9 @@ class $name(pu.PolyBase) : Return a `$name` instance that is the least squares fit to the data `y` sampled at `x`. Unlike `${nick}fit`, the domain of the returned instance can be specified and this will often result in a superior - fit with less chance of ill conditioning. See `${nick}fit` for full - documentation of the implementation. + fit with less chance of ill conditioning. Support for NA was added + in version 1.7.0. See `${nick}fit` for full documentation of the + implementation. Parameters ---------- |