Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/release/1.10.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,18 @@ deprecated.
pkgload, PackageLoader
~~~~~~~~~~~~~~~~~~~~~~
These ways of loading packages are now deprecated.

bias, ddof arguments to corrcoef
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The values for the ``bias`` and ``ddof`` arguments to the ``corrcoef``
function canceled in the division implied by the correlation coefficient and
so had no effect on the returned values.

We now deprecate these arguments to ``corrcoef`` and the masked array version
``ma.corrcoef``.

Because we are deprecating the ``bias`` argument to ``ma.corrcoef``, we also
deprecate the use of the ``allow_masked`` argument as a positional argument,
as its position will change with the removal of ``bias``. ``allow_masked``
will in due course become a keyword-only argument.
10 changes: 10 additions & 0 deletions numpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ class VisibleDeprecationWarning(UserWarning):
pass


class _NoValue:
"""Special keyword value.

This class may be used as the default value assigned to a
deprecated keyword in order to check if it has been given a user
defined value.
"""
pass

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two blank lines ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not export this publicly? Just call it _NoValue or something? We
have enough public clutter as it is, and this adds zero value.
On Mar 14, 2015 9:15 PM, "Charles Harris" [email protected] wrote:

In numpy/init.py
#5683 (comment):

@@ -132,6 +132,15 @@ class VisibleDeprecationWarning(UserWarning):
pass

+class NoValue:

  • """Special keyword value.
  • This class may be used as the default value assigned to a
  • deprecated keyword in order to check if it has been given a user
  • defined value.
  • """
  • pass

Two blank lines ;)


Reply to this email directly or view it on GitHub
https://github.com/numpy/numpy/pull/5683/files#r26444409.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess it doesn't need to be public, so _NoValue would work.


# oldnumeric and numarray were removed in 1.9. In case some packages import
# but do not use them, we define them here for backward compatibility.
oldnumeric = 'removed'
Expand Down
39 changes: 22 additions & 17 deletions numpy/lib/function_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1949,17 +1949,17 @@ def cov(m, y=None, rowvar=1, bias=0, ddof=None):
return (dot(X, X.T.conj()) / fact).squeeze()


def corrcoef(x, y=None, rowvar=1, bias=0, ddof=None):
def corrcoef(x, y=None, rowvar=1, bias=np._NoValue, ddof=np._NoValue):
"""
Return correlation coefficients.
Return Pearson product-moment correlation coefficients.

Please refer to the documentation for `cov` for more detail. The
relationship between the correlation coefficient matrix, `P`, and the
relationship between the correlation coefficient matrix, `R`, and the
covariance matrix, `C`, is

.. math:: P_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} * C_{jj} } }
.. math:: R_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} * C_{jj} } }

The values of `P` are between -1 and 1, inclusive.
The values of `R` are between -1 and 1, inclusive.

Parameters
----------
Expand All @@ -1975,28 +1975,33 @@ def corrcoef(x, y=None, rowvar=1, bias=0, ddof=None):
variable, with observations in the columns. Otherwise, the relationship
is transposed: each column represents a variable, while the rows
contain observations.
bias : int, optional
Default normalization is by ``(N - 1)``, where ``N`` is the number of
observations (unbiased estimate). If `bias` is 1, then
normalization is by ``N``. These values can be overridden by using
the keyword ``ddof`` in numpy versions >= 1.5.
ddof : int, optional
.. versionadded:: 1.5
If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
the number of observations; this overrides the value implied by
``bias``. The default value is ``None``.
bias : _NoValue, optional
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably keep the documentation for both of these, but just say they have no affect and are deprecated. Like so

    bias :
        .. deprecated:: 1.10.0
        Has no affect, not used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make that

    bias : NoValue, optional
        .. deprecated:: 1.10.0
        Has no affect, do not use.

.. deprecated:: 1.10.0
Has no affect, do not use.
ddof : _NoValue, optional
.. deprecated:: 1.10.0
Has no affect, do not use.

Returns
-------
out : ndarray
R : ndarray
The correlation coefficient matrix of the variables.

See Also
--------
cov : Covariance matrix

Notes
-----
This function accepts but discards arguments `bias` and `ddof`. This is
for backwards compatibility with previous versions of this function. These
arguments had no effect on the return values of the function and can be
safely ignored in this and previous versions of numpy.
"""
c = cov(x, y, rowvar, bias, ddof)
if bias is not np._NoValue or ddof is not np._NoValue:
warnings.warn('bias and ddof have no affect and are deprecated',
DeprecationWarning)
c = cov(x, y, rowvar)
try:
d = diag(c)
except ValueError: # scalar covariance
Expand Down
38 changes: 28 additions & 10 deletions numpy/lib/tests/test_function_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
run_module_suite, TestCase, assert_, assert_equal, assert_array_equal,
assert_almost_equal, assert_array_almost_equal, assert_raises,
assert_allclose, assert_array_max_ulp, assert_warns,
assert_raises_regex, dec
assert_raises_regex, dec, clear_and_catch_warnings
)
import numpy.lib.function_base as nfb
from numpy.random import rand
from numpy.lib import *
from numpy.compat import long
Expand Down Expand Up @@ -1305,6 +1306,12 @@ def test_dtype_order(self):
assert_(a.dtype == np.float64)


class catch_warn_nfb(clear_and_catch_warnings):
""" Context manager to catch, reset warnings in function_base module
"""
class_modules = (nfb,)


class TestCorrCoef(TestCase):
A = np.array(
[[0.15391142, 0.18045767, 0.14197213],
Expand Down Expand Up @@ -1335,8 +1342,26 @@ def test_simple(self):
assert_almost_equal(corrcoef(self.A, self.B), self.res2)

def test_ddof(self):
assert_almost_equal(corrcoef(self.A, ddof=-1), self.res1)
assert_almost_equal(corrcoef(self.A, self.B, ddof=-1), self.res2)
# ddof raises DeprecationWarning
with catch_warn_nfb():
warnings.simplefilter("always")
assert_warns(DeprecationWarning, corrcoef, self.A, ddof=-1)
warnings.simplefilter("ignore")
# ddof has no or negligible effect on the function
assert_almost_equal(corrcoef(self.A, ddof=-1), self.res1)
assert_almost_equal(corrcoef(self.A, self.B, ddof=-1), self.res2)
assert_almost_equal(corrcoef(self.A, ddof=3), self.res1)
assert_almost_equal(corrcoef(self.A, self.B, ddof=3), self.res2)

def test_bias(self):
# bias raises DeprecationWarning
with catch_warn_nfb():
warnings.simplefilter("always")
assert_warns(DeprecationWarning, corrcoef, self.A, self.B, 1, 0)
assert_warns(DeprecationWarning, corrcoef, self.A, bias=0)
warnings.simplefilter("ignore")
# bias has no or negligible effect on the function
assert_almost_equal(corrcoef(self.A, bias=1), self.res1)

def test_complex(self):
x = np.array([[1, 2, 3], [1j, 2j, 3j]])
Expand All @@ -1356,13 +1381,6 @@ def test_empty(self):
assert_array_equal(corrcoef(np.array([]).reshape(2, 0)),
np.array([[np.nan, np.nan], [np.nan, np.nan]]))

def test_wrong_ddof(self):
x = np.array([[0, 2], [1, 1], [2, 0]]).T
with warnings.catch_warnings(record=True):
warnings.simplefilter('always', RuntimeWarning)
assert_array_equal(corrcoef(x, ddof=5),
np.array([[np.nan, np.nan], [np.nan, np.nan]]))


class TestCov(TestCase):
def test_basic(self):
Expand Down
54 changes: 25 additions & 29 deletions numpy/ma/extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
from numpy import ndarray, array as nxarray
import numpy.core.umath as umath
from numpy.lib.index_tricks import AxisConcatenator
from numpy.linalg import lstsq


#...............................................................................
Expand Down Expand Up @@ -1377,9 +1376,10 @@ def cov(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
return result


def corrcoef(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, allow_masked=True,
ddof=np._NoValue):
"""
Return correlation coefficients of the input array.
Return Pearson product-moment correlation coefficients.

Except for the handling of missing data this function does the same as
`numpy.corrcoef`. For more details and examples, see `numpy.corrcoef`.
Expand All @@ -1398,45 +1398,41 @@ def corrcoef(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
variable, with observations in the columns. Otherwise, the relationship
is transposed: each column represents a variable, while the rows
contain observations.
bias : bool, optional
Default normalization (False) is by ``(N-1)``, where ``N`` is the
number of observations given (unbiased estimate). If `bias` is 1,
then normalization is by ``N``. This keyword can be overridden by
the keyword ``ddof`` in numpy versions >= 1.5.
bias : _NoValue, optional
.. deprecated:: 1.10.0
Has no affect, do not use.
allow_masked : bool, optional
If True, masked values are propagated pair-wise: if a value is masked
in `x`, the corresponding value is masked in `y`.
If False, raises an exception.
ddof : {None, int}, optional
.. versionadded:: 1.5
If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
the number of observations; this overrides the value implied by
``bias``. The default value is ``None``.
If False, raises an exception. Because `bias` is deprecated, this
argument needs to be treated as keyword only to avoid a warning.
ddof : _NoValue, optional
.. deprecated:: 1.10.0
Has no affect, do not use.

See Also
--------
numpy.corrcoef : Equivalent function in top-level NumPy module.
cov : Estimate the covariance matrix.

"""
# Check inputs
if ddof is not None and ddof != int(ddof):
raise ValueError("ddof must be an integer")
# Set up ddof
if ddof is None:
if bias:
ddof = 0
else:
ddof = 1

Notes
-----
This function accepts but discards arguments `bias` and `ddof`. This is
for backwards compatibility with previous versions of this function. These
arguments had no effect on the return values of the function and can be
safely ignored in this and previous versions of numpy.
"""
msg = 'bias and ddof have no affect and are deprecated'
if bias is not np._NoValue or ddof is not np._NoValue:
warnings.warn(msg, DeprecationWarning)
# Get the data
(x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)
# Compute the covariance matrix
if not rowvar:
fact = np.dot(xnotmask.T, xnotmask) * 1. - ddof
fact = np.dot(xnotmask.T, xnotmask) * 1.
c = (dot(x.T, x.conj(), strict=False) / fact).squeeze()
else:
fact = np.dot(xnotmask, xnotmask.T) * 1. - ddof
fact = np.dot(xnotmask, xnotmask.T) * 1.
c = (dot(x, x.T.conj(), strict=False) / fact).squeeze()
# Check whether we have a scalar
try:
Expand All @@ -1452,13 +1448,13 @@ def corrcoef(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
if rowvar:
for i in range(n - 1):
for j in range(i + 1, n):
_x = mask_cols(vstack((x[i], x[j]))).var(axis=1, ddof=ddof)
_x = mask_cols(vstack((x[i], x[j]))).var(axis=1)
_denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))
else:
for i in range(n - 1):
for j in range(i + 1, n):
_x = mask_cols(
vstack((x[:, i], x[:, j]))).var(axis=1, ddof=ddof)
vstack((x[:, i], x[:, j]))).var(axis=1)
_denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))
return c / _denom

Expand Down
Loading