Skip to content

BUG: Masked arrays and apply_over_axes #4463

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

Merged
merged 1 commit into from
Apr 3, 2014
Merged

Conversation

abalkin
Copy link
Contributor

@abalkin abalkin commented Mar 9, 2014

Masked arrays version of apply_over_axes did not apply
function correctly to arrays with non-trivial masks.

Fixes #4461.

@@ -416,24 +416,23 @@ def apply_over_axes(func, a, axes):
"""
(This docstring will be overwritten)
"""
val = np.asarray(a)
msk = getmaskarray(a)
val = asarray(a)
N = a.ndim
if array(axes).ndim == 0:
axes = (axes,)
for axis in axes:
if axis < 0: axis = N + axis
Copy link
Member

Choose a reason for hiding this comment

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

Please clean that up a bit by putting axis = N + axis on the next line. I know it wasn't yours to begin with ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I copied the entire body of this function from np.apply_over_axes. I don't mind cleaning it up a bit, but I don't want to introduce spurious differences between the two functions. Should I reformat np.apply_over_axes as well?

Copy link
Member

Choose a reason for hiding this comment

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

Sure, make it a different commit though.The message prefix would be STY:.

@charris
Copy link
Member

charris commented Mar 10, 2014

I looks like func is left to handle the mask on it's own. That looks different from the original, although the original mask handling looks a bit odd also. In any case, it seems to me it would be good to document what the function is supposed to do with the mask.

N = a.ndim
if array(axes).ndim == 0:
axes = (axes,)
for axis in axes:
if axis < 0: axis = N + axis
args = (val, axis)
res = ma.array(func(*(val, axis)), mask=func(*(msk, axis)))
res = func(*args)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is another place that could use a clean-up. I would simply write func(val, axis) in the line above.

Copy link
Member

Choose a reason for hiding this comment

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

What about the mask=func(*(msk, axis))? That is what concerned me. The original does something with the mask, the new version doesn't.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This made no sense to me. And neither did f(*(a, b)) instead of f(a, b). Looks like a bit of overengineering.

ma.apply_over_axes inherits docstring from np.apply_over_axes, so it should work the same way and delegate mask handling to func. This is what the OP issue was about.

Copy link
Member

Choose a reason for hiding this comment

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

OK. Agree about the f(*(a, b)) function call. Can that be cleaned up without too much trouble? Also, even though the docstring is currently inherited, it might make sense to have one where you can mention that the mask handling is left to func.

@charris
Copy link
Member

charris commented Mar 23, 2014

@abalkin Can you finish this up? I'd like to put it in.

@abalkin
Copy link
Contributor Author

abalkin commented Mar 23, 2014

@charris - I replaced np example with ma one in docstring. Note that the "Notes" section is also not applicable directly to ma case because ma.sum does not support keepdims. See #4537.

raise ValueError("Function is not returning"\
" an array of correct shape")
raise ValueError("function is not returning "
"an array of the correct shape")
Copy link
Member

Choose a reason for hiding this comment

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

PEP8, but this will get fixed later when we pepify these files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was copied from np.apply_over_axes. I assume "pepify" will fix this in both places.

Copy link
Member

Choose a reason for hiding this comment

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

In particular, the indent should be

                raise ValueError("function is not returning"
                                 " an array of the correct shape")

or

                raise ValueError(
                    "function is not returning an array of the correct shape")

@charris
Copy link
Member

charris commented Apr 1, 2014

@abalkin Be good to get this finished up.

Masked arrays version of apply_over_axes did not apply
function correctly to arrays with non-trivial masks.

Fixes numpy#4461.
@abalkin
Copy link
Contributor Author

abalkin commented Apr 2, 2014

@charris - this should be good to go.

@charris
Copy link
Member

charris commented Apr 3, 2014

In it goes. We'll see if this change causes any problems. Thanks @abalkin.

charris added a commit that referenced this pull request Apr 3, 2014
BUG: Masked arrays and apply_over_axes
@charris charris merged commit 3998fdf into numpy:master Apr 3, 2014
@rgommers
Copy link
Member

Looks like this broke something: gh-4627

@charris
Copy link
Member

charris commented Apr 21, 2014

@abalkin I'd guess this comes from not applying the function to the mask.

@abalkin
Copy link
Contributor Author

abalkin commented Apr 21, 2014

@charris - can you demonstrate the regression in a simple case? I am not familiar with scipy.stats.mstats.trim.

@rgommers
Copy link
Member

Found the issue: it's because trim was relying on apply_over_axes making a copy of the input. The first line of this patch changes that by using np.ma.asarray.

The new behavior is arguably better, but this PR may still silently break working code. Therefore I think we should restore the copy behavior.

@abalkin
Copy link
Contributor Author

abalkin commented Apr 21, 2014

@rgommers - does trim work only with masked arrays?

@abalkin
Copy link
Contributor Author

abalkin commented Apr 21, 2014

It looks like trim converts any input to masked array. Please ignore my question above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Masked arrays and apply_over_axes
3 participants