简体   繁体   中英

Add vectors as objects to numpy array with boolean indexing - 2D arrays work, 1D arrays do not

I want to assign vectors to a numpy array to make convenient use of the boolean indexing. It worked, until I hit a corner case. Minimal working example:

a = np.array([None] * 2)
b = [np.ones(shape=[1, 3]), np.ones(shape=[2, 4])]
a[True, True] = b  # Works as intended

print(a)

However, when all arrays are 1D, I get an error:

a = np.array([None] * 2)
b = [np.ones(shape=[1, 3]), np.ones(shape=[1, 4])]  # shape of second array changed!
a[True, True] = b  # ValueError: cannot copy sequence with size 2 to array axis with dimension 1

Any ideas how I can avoid this? (I checked on both numpy versions v1.19.5 and v1.21.1)

I solved it. If you use a np.where, the code runs. Not sure why. Example:

a = np.array([None] * 2)
b = [np.ones(shape=[1, 3]), np.ones(shape=[1, 4])]  # shape of second array changed!
a[np.where([True, True])] = b  # Works as intended.

print(a)
In [436]: a[True,True]=b
Traceback (most recent call last):
  File "<ipython-input-436-7c0409496970>", line 1, in <module>
    a[True,True]=b
ValueError: could not broadcast input array from shape (3,) into shape (1,)

Looks like this masked assignment is first converting b to an array:

In [437]: np.array(b)
<ipython-input-437-cbcacfae87b2>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  np.array(b)
Traceback (most recent call last):
  File "<ipython-input-437-cbcacfae87b2>", line 1, in <module>
    np.array(b)
ValueError: could not broadcast input array from shape (3,) into shape (1,)

But (as experienced users know), trying to make an array from arrays that match in the first dimension (1), but not the second, raises this error.

Your in your first case the b arrays differ in the first axis, and np.array(b) produces a 2 element object dtype array.

These assignments don't, apparently, do the np.array(b) :

In [439]: a[:]=b
In [440]: a
Out[440]: array([array([[1., 1., 1.]]), array([[1., 1., 1., 1.]])], dtype=object)
In [441]: a[[0,1]]=b
In [442]: a
Out[442]: array([array([[1., 1., 1.]]), array([[1., 1., 1., 1.]])], dtype=object)

Assigning a 'proper' object dtype array does work:

In [447]: a[[True,True]]=a.copy()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM