-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MRG: deprecate ddof / bias args to corrcoef #5675
MRG: deprecate ddof / bias args to corrcoef #5675
Conversation
You mean "context manager", not " decorator". Everything else looks good to
|
Warnings can be slippery, because, whenever a warning is triggered, Python adds a __warningregistry__ member to the *calling* module. This makes it impossible to retrigger the warning in this module, whatever you put in simplefilter. The `catch_warn_reset` decorator removes the __warningregistry__ member as the context manager exits, making it possible to retrigger the warning.
The `ddof` and `bias` arguments to `corrcoef` cancel in the math of the correlation coefficient, so there is no point in passing these values, and it is confusing to the user to see these in the docstring. Remove, deprecate, and test.
40bf776
to
e88b608
Compare
Thanks - I fixed references to 'decorator'. The main question that I have is what to do about the 'bias' argument to It might be prudent to plan to make |
arguments had no effect on the return values of the function and can be | ||
safely ignored in this and previous versions of numpy. | ||
""" | ||
if len(args) or kwargs.pop('bias', _DefaultArg) is not _DefaultArg: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are opening the door to lots of nonsense input going through silently, e.g. extra keyword or positional arguments, bias
and ddof
being provided as both positional and keyword simultaneously... May not be worth adding all those checks for something we actually want to deprecate, but...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking for simultaneous positional and keyword does seem too much for arguments that don't have any effect on the function. We are already warning about their use.
It's easy to check for the length of args and kwargs after parsing though.
"allow_masked" follows "bias" argument, but "bias" will go away at some point. Intend that we will make "allow_masked" keyword only at the same time that we remove "bias".
Raise errors for the wrong number of positional arguments or incorrect keyword arguments in corrcoef routines.
I added a deprecation warning for I added checks for number of positional args and unexpected keyword args. |
@@ -48,7 +48,7 @@ | |||
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 | |||
from numpy.lib.function_base import _CORRCOEF_MSG_FMT, _DefaultArg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just repeat the definition here. This import complicates the code, obscures the value of _CORRCOEF_MSG_FMT, and introduces a dependency between modules. The format is temporary anyway. No reason not to also put the private _DefaultArg
here also, and for the same reasons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Willco.
Any suggestions for a good place for _DefaultArg
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since its use is entirely local, it might be better to just define it in each module in which it is used. It is going to be temporary, at least in the numpy sense of temporary. Otherwise, I might suggest numpy/__init__.py
, which already has a couple of global classes. In the latter case a more suggestive name might help.
Rather than importing the small code support fragments from function_base.py, replicate them to make the code easier to read.
Note that this is the Pearson product-moment correlation. Note the pending change of allow_masked to keyword-only.
Add ability to add default modules to catch_warn_reset classs, by inheritance.
Both the deprecation and context manager should be mentioned in the release notes. Apropos the context manager, a separate PR might be best. A name closer to the standard |
Or maybe |
Use inheritance of catch_warn_reset for slightly cleaner context managers.
No problem for separate PR, and renaming of context manager. Adding to Sckit-image go for a more magic and more nuclear solution, always clearing out all recorded previous warnings for modules in the call stack: https://github.com/scikit-image/scikit-image/blob/master/skimage/_shared/_warnings.py |
Google also turned up that nuclear option. So there is no easy way to know what module a warning was raised in when it is caught? |
I don't know of any way to find out what module the warning was raised in, from the warning itself... |
Thinking about it, both the format and class could be local to the function, that way everything could be deleted at one go when it comes to that. |
My worry about putting the class definition and format string in the funciton was that it made the meat of the function harder to read. I can imagine that it might be distracting to see this little piece of uncecessarily repeated work inside the function. |
Good point. OTOH, if it is outside the function one wonders where else it is used. |
Move the format strings into the function, as they are only used in the function.
I was hoping that wondering where else it is used it more typical of the keen-eyed maintainer than the casual developer or user. I've moved just the string into the function - how about that? |
OK. Too bad we can't just use |
My worry with None is that it's not possible to tell whether the user passed it, thinking the argument still existed. |
How about just check for the key, then pop it if present and issue the warning? |
Your nit-pick is my command. If this is all good I'll rebase into two PRs. |
warnings.warn(fmt.format('ddof'), DeprecationWarning) | ||
if len(kwargs): | ||
raise TypeError( | ||
"corrcoef got an unexpected keyword argument '{0}'".format( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that you can break this line
raise TypeError("corrcoef got an unexpected keyword "
"argument '{0}'".format(list(kwargs)[0])
LGTM, go for it. I tossed in another nitpick... |
OK to rename context manager to |
I'd probably leave the |
Although I confess to being a bit unsure why the context manager is needed. Does this fix a problem when the tests are run in interactive mode? |
I moved the context manager into |
OK to go ahead with 2 PRs from this state? |
@@ -1,10 +1,16 @@ | |||
from __future__ import division, absolute_import, print_function | |||
|
|||
import warnings | |||
from warnings import warn, simplefilter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually just import warnings and use it in the warnings.warn
form.
Sure. I won't guarantee no more comments, but I think this is getting close. |
d81d18a
to
c1f5e99
Compare
Maybe the context manager should better be called |
Or |
OK - I think this is ready now - will split into separate PRs soon. |
Context manager PR here : #5682 |
Deprecation stuff here : #5683 |
OK, I'll close this now. |
As discussed on the mailing list, the values for the bias and ddof
arguments to the corrcoef cancel in calculation, and are therefore
pointless and confusing.
Deprecate these arguments and document their pending removal.
This PR also includes a version of the warnings.catch_warnings decorator
that allows warnings to be tested for multiple times without error.