Skip to content
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

Inconsistency in assignment to object array. #6074

Closed
dimasad opened this issue Jul 13, 2015 · 9 comments
Closed

Inconsistency in assignment to object array. #6074

dimasad opened this issue Jul 13, 2015 · 9 comments
Labels
57 - Close? Issues which may be closable unless discussion continued

Comments

@dimasad
Copy link
Contributor

dimasad commented Jul 13, 2015

Consider the following code:

>>> import numpy as np
>>> x = np.zeros((1,1), dtype=object)
>>> y = np.zeros((1,1), dtype=object)
>>> z = np.zeros((1,1), dtype=object)
>>> a = np.array(None)
>>> x[0] = a
>>> y[0,0,...] = a
>>> z[0,0] = a
>>> x
array([[None]], dtype=object)
>>> y
array([[None]], dtype=object)
>>> z ### This is inconsistent!!!!
array([[array(None, dtype=object)]], dtype=object) 

As it can be seen, assignment of a zero-rank array to an object array causes nesting of array inside an array. I believe that the third case (assignment to z) should behave like the other cases, otherwise one can quickly generate arrays inside arrays inside arrays and necessitate extra code to treat special cases.

This was tested in numpy 1.9.2 under python 3.4.2.

dimasad added a commit to cea-ufmg/sym2num that referenced this issue Jul 13, 2015
@seberg
Copy link
Member

seberg commented Jul 14, 2015

Well, in its own twisted way, it actually is consistent. Unlike the other two, z is a scalar assignment (i.e. the result of the indexing np.array([[None]])[0, 0] gives back None and not np.array(None) as in the other two cases.
We can argue about the scalar vs. 0-d array result, but I am not sure there is a nice way to get around these kind of issues with object arrays, considering there is a difference between scalar and 0-d indexing.

@seberg
Copy link
Member

seberg commented Jul 14, 2015

You could look it the other way around. If this was not the case, I do not think there would be any possibility to put an array into another array! ;)
EDIT: OK that may be overstating, but you would probably have to do a dance to achieve it.

@seberg seberg added the 57 - Close? Issues which may be closable unless discussion continued label Jul 14, 2015
@leewz
Copy link

leewz commented Jul 14, 2015

Yeah, the third one is a level deeper than the other two. Whatever the proper behavior is, it should NOT be the same as the other two.

See #6070, which suggests that e.g. array(None) shouldn't work without specifying dtype.

@dimasad
Copy link
Contributor Author

dimasad commented Jul 14, 2015

I was also thinking about consistency with respect to numerical arrays, since for them we have the following behaviour:

>>> x = np.zeros((1,1), int)
>>> a = np.ones((), int)
>>> x[0,0] = a
>>> x
array([[1]])

Anyways, I had not thought of putting an ndarray inside an ndarray as a valid use-case. If that is so then this issue might simply be a feature. I think, however, that when ndarrays start to nest like that it is usually unwanted.

With respect to @leewz's comment, I used array(None) intentionally simply as a shorthand for array(None, dtype=object). The same behavior would happen if I had used a = np.ones((), dtype=object).

@seberg
Copy link
Member

seberg commented Jul 14, 2015

Yes, though you could argue that the way you get there is at least in principle reversed. It is not so much that the right hand side takes the element from the left hand side in the assignment. It is that the left hand side says that it can be interpreted as an integer (since it is 0-d).
Looking from that side you would have to make the int example an error probably, though that is likely unnecessary hassle.

@ahaldane
Copy link
Member

Just to add to comments above: Assigning to object arrays is a special case that behaves differently from non-object arrays, specifically to allow nesting of ndarrays. For example, this special case is explicit in this code.

See also http://stackoverflow.com/questions/3273040/numpy-object-array-of-numerical-arrays

This is one of a couple "special" things about object arrays I think should be documented. (Another is the "special" casting rules that apply to object arrays). I think a little dedicated section on object arrays in the user docs would be good. Probably it should wait until some issues related to object arrays are decided though.

@dimasad
Copy link
Contributor Author

dimasad commented Jul 16, 2015

I think it's safe to close this, then. I guess the simplest workaround to get the behavior I want is to always include the ellipsis for item assignment. Object arrays are tricky to work with but can help a great deal when working with sympy objects, for example.

@argriffing
Copy link
Contributor

Here's a thing that seems inconsistent to me:

>>> a = np.array([[1, 2], [3, 4]])
>>> b = np.array([[1, 2, 3], [4, 5, 6]])
>>> np.array([a, b])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (2,2) into shape (2)

but

>>> np.array([ [[1, 2], [3, 4]], [[1, 2, 3], [4, 5, 6]] ])
array([[[1, 2], [3, 4]],
       [[1, 2, 3], [4, 5, 6]]], dtype=object)

It seems inconsistent that one creates an object array, but the other one does not (and gives an error instead).

@leewz
Copy link

leewz commented Nov 12, 2015

Honestly, I prefer it that way. Numpy is for numbers. If you want something weird, you should have to explicitly say so. It should give you an error if you accidentally ask for something weird, and I can see that being an accident.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
57 - Close? Issues which may be closable unless discussion continued
Projects
None yet
Development

No branches or pull requests

5 participants