How do I fix a NumPy ValueError for an inhomogeneous array shape?

56 Views Asked by At

For this section of code, I am trying to randomly choose either theta or mu to be zero. When one variable is zero, then I need the other one uniformly randomized (and vice versa).

N = 10000

random = np.arccos(np.random.uniform(-1, 1, N))
zero = 0
choices = [random, zero]
theta = np.random.choice(choices)

if theta == random:
  mu = zero
else:
  mu = random

I know that random and zero do not have a homogenous shape.

This is why I got the error:

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.

However, I do not know how to fix this (I am still very new to programming). Any thoughts would be appreciated.

3

There are 3 best solutions below

0
Nick ODell On

You wouldn't really want to use np.random.choice() here, because it doesn't take an axis parameter, so it can't be vectorized. It would be better to create a boolean mask from a random variable, and use that to select whether the random value goes into the mu or theta variable. np.where() can do that.

Example:

random = np.arccos(np.random.uniform(-1, 1, N))
mask = np.random.uniform(size=N) < 0.5
theta = np.where(mask, random, 0)
mu = np.where(mask, 0, random)
0
anatolyg On

You can generate a random index to an array instead of taking a random array element directly.

theta_chice = np.random.choice(2)
theta = choices[theta_chice]
mu = choices[1 - theta_chice]

Note: another answer provides a way to take independent random decisions for each of the N indices. This answer takes just one decision. Not sure what you wanted.

0
hpaulj On

Your initial code makes an array and an int variable:

In [277]: random = np.arccos(np.random.uniform(-1, 1, 1000))
     ...: zero = 0
     ...: choices = [random, zero]
In [278]: random.shape
Out[278]: (1000,)

Trying to do choices on the list raises the same error as trying to make an array from the list:

In [279]: np.array(choices)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[279], line 1
----> 1 np.array(choices)

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.

In [280]: theta = np.random.choice(choices)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[280], line 1
----> 1 theta = np.random.choice(choices)

File mtrand.pyx:920, in numpy.random.mtrand.RandomState.choice()

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.

If I apply choice to the array, I get one value from the array:

In [281]: theta = np.random.choice(random)    
In [282]: theta
Out[282]: 1.3589184926442504

Similarly, a choice from a list:

In [284]: np.random.choice([1,2,3,4])
Out[284]: 2
In [285]: type(_)
Out[285]: numpy.int32

The type of this choice is further clue that it has first converted the list to an array.

Your if line will also have a problem. random is an array, so the == will be a boolean array. That can't be used in a if expression:

In [283]: if theta == random: pass
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[283], line 1
----> 1 if theta == random: pass

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Assuming you want the array for one variable, and zero for the other, it would be better to apply the choice to the if directly:

In [290]: x = np.random.choice(2, size=10);x
Out[290]: array([1, 1, 0, 0, 0, 0, 1, 0, 1, 0])

For a single random True/False I'd prefer to use the random module, but you've already used that variable name, so I'll stick with choice.

In [291]: if np.random.choice(2):
     ...:     theta = random
     ...:     mu = zero
     ...: else:
     ...:     theta = zero
     ...:     mu = random
     ...:     

In [292]: theta, mu
Out[292]: 
(array([2.21440251, 0.70140386, 2.66193561, 1.52018933, 1.0636733 ,
        2.33811607, 0.98158435, 1.85139822, 0.27636737, 1.55758632,...

You could modify this if/else if instead you want a random float instead of the whole array (as in [281]).