Thanks to visit codestin.com
Credit goes to github.com

Skip to content

.view no longer works on field selections of structured arrays #10409

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

Closed
eric-wieser opened this issue Jan 16, 2018 · 12 comments · Fixed by #12447
Closed

.view no longer works on field selections of structured arrays #10409

eric-wieser opened this issue Jan 16, 2018 · 12 comments · Fixed by #12447

Comments

@eric-wieser
Copy link
Member

eric-wieser commented Jan 16, 2018

See this SO question:

>>> some_data = np.array([('foo', 3.5, 2.15), ('bar', 2.8, 5.3), ('baz', 1.2, 3.7)], 
                     dtype=[('col1', '<U20'), ('A', '<f8'), ('B', '<f8')])
>>> ab = some_data[['A', 'B']]
>>> np.__version__
'1.13.3'
>>> ab.dtype
dtype([('A', '<f8'), ('B', '<f8')])
>>> ab.view(('<f8', 2))
FutureWarning: Numpy has detected that you may be viewing or writing to an array returned by selecting multiple fields in a structured array. 

This code may break in numpy 1.13 because this will return a view instead of a copy -- see release notes for details.
array([[ 3.5 ,  2.15],
       [ 2.8 ,  5.3 ],
       [ 1.2 ,  3.7 ]])

vs

>>> np.__version__
'1.15.0.dev...'
>>> ab.dtype
dtype({'names':['A','B'], 'formats':['<f8','<f8'], 'offsets':[80,88], 'itemsize':96})
>>> ab.view(('<f8', 2))
ValueError: Changing the dtype to a subarray type is only supported if the total itemsize is unchanged

Since we now return a view rather than a copy from arr[fields], we end up with a dtype with padding. This prevents .view being called, even though the memory layout is sufficient to allow it

@ahaldane
Copy link
Member

Yeah, I explicitly mentioned this in the 1.13 and 1.14 release notes. Actually, since we have not provided a pack_fields method it is difficult for downstream users to update their code to get the old behavior: I originally thought the user could just replace arr[fields'] by arr[fields].copy(), but that does not remove padding bytes either.

@charris charris added this to the 1.14.1 release milestone Feb 3, 2018
ahaldane added a commit to ahaldane/numpy that referenced this issue Feb 3, 2018
ahaldane added a commit to ahaldane/numpy that referenced this issue Feb 3, 2018
ahaldane added a commit to ahaldane/numpy that referenced this issue Feb 3, 2018
ahaldane added a commit to ahaldane/numpy that referenced this issue Feb 7, 2018
@charris charris modified the milestones: 1.14.1 release, 1.15.0 release Feb 8, 2018
@eric-wieser
Copy link
Member Author

eric-wieser commented Jun 10, 2018

Should slicing a dtype shrink the itemsize?

ie, if a dtype has fields a, b, c, d, and you slice with ['b', 'd'], should the resulting view dtype still span the entire original, or just the fields selected? Doing the latter would solve the problem for contiguous views within dtypes (which are probably most common)

A consequence of this would be that the resulting array would be non-"contiguous"

@ahaldane
Copy link
Member

ahaldane commented Jun 11, 2018

You mean like arr[['b', 'c']].view('i8') if all the fields are originally i4. True, that could potentially be allowed.

On the other hand sometimes it's better to fail more rather than less often. If people get errors about viewing multifield slices more easily, maybe that's better than hiding it in special cases. Then people are forced to write code that is safe in all situations, for example using repack_fields.

@eric-wieser
Copy link
Member Author

eric-wieser commented Jun 11, 2018

Even the less objectionable case where the dtypes match

dt = np.dtype([
    ('a', np.int16),
    ('b', np.int16),
    ('c', np.int16),
])
arr = np.empty(10, dt)

# both of these no longer work, but could have well-defined behavior
arr[['a']].view(np.int16)
arr[['a', 'b']].view((np.int16, 2))

Essentially, I'm proposing a trim_fields behavior, where one offset is always zero, and the itemsize is never beyond the element occupying the last byte

@ahaldane
Copy link
Member

ahaldane commented Jun 11, 2018

Right, but it still bothers me that arr[['a', 'c']].view((np.int16, 2)) would still fail, which would be unexpected so someone who found that [['a', 'b']] worked. It might be better to force the user to write repack_fields(arr[['a', 'c']]).view((np.int16, 2)) in all 3 cases.

Also, I'm pretty sure that even with this trim_fields behavior the view often isn't allowed because the resulting array is not C-contiguous. Compare to:

>>> a = np.ones((10,3), dtype='i4')
>>> a[:,0:2].view('i8')
ValueError: To change to a dtype of a different size, the array must be C-contiguous
>>> a[:,0:2].view(('i4', 2))
ValueError: Changing the dtype to a subarray type is only supported if the total itemsize is unchanged

@charris
Copy link
Member

charris commented Jun 11, 2018

@ahaldane Is this now fixed for 1.15?

@ahaldane
Copy link
Member

Yes, I just checked master. Master now gives the 1.13 behavior, just with an updated futurewarning.

I'm not sure we should close, since this issue will pop up again in 1.16.

@charris
Copy link
Member

charris commented Jun 11, 2018

Good, I'll just update the milestone :).

@charris charris removed this from the 1.15.0 release milestone Jun 11, 2018
@charris charris added this to the 1.16.0 release milestone Jun 11, 2018
@mattip
Copy link
Member

mattip commented Jul 6, 2018

I ran across code in mapping.c that is marked for removal in 1.16, but could not find a pull request that is waiting for a merge. It seems there is work to be done here?

@ahaldane
Copy link
Member

ahaldane commented Jul 7, 2018

Yes, that's on my TODO list. See discussion in #10411, essentially we need to fix #8100 first.

I should have some time to work on it starting in two weeks, but feel free to take a shot at it before. There is already some work on it in #10931 but as I comment there a more extensive fix is needed.

@mattip
Copy link
Member

mattip commented Aug 14, 2018

We have returned to the 1.13 behavior now. PR #10411 was merged, issue #8100 is closed. Can we close this or do we want to explore returning views again?

@ahaldane
Copy link
Member

Hmm in my opinion #8100 was mistakenly closed, since I accidentally used the word "fix" in a sentence in #10411's description.

I am also not sure we've made a decision about structured views. As far as I am aware (I was out for a bit so may have missed it) I think we are still considering turning it into a view. #10411 just pushed off the decision/implementation.

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 a pull request may close this issue.

4 participants