0

This is my code, and I get the following error:

ValueError: NumPy boolean array indexing assignment cannot assign 100 input values to the 90 output values where the mask is true. The error is on the line assigning a value for V.

What am I doing wrong?

from pylab import * 
import numpy as np
from math import *
r = np.linspace(0, 10, 100)

V = np.piecewise(r, [r < 1, r > 1 ], [1, (r/2)*(3 - (r**2))])

#Graph of V r / k q vs. r/R for unitless quantities

figure()
plot(r, V)
xlabel('r / R') 
ylabel('V r / k q') 
title('Behavior of V(r) vs r')

ax = plt.gca()

ax.set_xticks([1])
  
ax.set_xticklabels(['R'])

plt.tick_params(left = False, right = False , labelleft = False)

grid()

show()
3
  • What are you doing wrong? For a start you didn't show the traceback or tell us which like caused the problem Commented Sep 23, 2021 at 1:23
  • The 3rd argument to piecewise is supposed contain scalars or functions, not arrays. Commented Sep 23, 2021 at 1:28
  • why not just concatenate 10 1's onto the 90 values for r>1. piecewise is overkill, especially since you don't seen to understand its argument requirements. Commented Sep 23, 2021 at 6:50

2 Answers 2

1

First your error with full traceback:

In [1]: r = np.linspace(0, 3, 20)
In [2]: V = np.piecewise(r, [r < 1, r > 1 ], [1, (r/2)*(3 - (r**2))])
Traceback (most recent call last):
  File "<ipython-input-2-0bb13126761c>", line 1, in <module>
    V = np.piecewise(r, [r < 1, r > 1 ], [1, (r/2)*(3 - (r**2))])
  File "<__array_function__ internals>", line 5, in piecewise
  File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 612, in piecewise
    y[cond] = func
ValueError: NumPy boolean array indexing assignment cannot assign 20 input values to the 13 output values where the mask is true

The problem is in piecewise. If you (re)read its docs, you'll see that the elements of the 3rd argument list are supposed to scalars or functions. You provided an array as the 2nd.

In [4]: np.size((r/2)*(3 - (r**2)))
Out[4]: 20
In [5]: np.sum(r<1), np.sum(r>1)
Out[5]: (7, 13)

piecewise is trying to assign 7 values from one condition to the array, and 13 for the other. That's why its complaining when you provide all 20 for the 2nd. 20 does not match 13!

If both values are scalar:

In [6]: V = np.piecewise(r, [r < 1, r > 1 ], [1, 2])
In [7]: V
Out[7]: 
array([1., 1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
       2., 2., 2.])

We could use a lambda function that will evaluate just the 13 values we want:

In [8]: V = np.piecewise(r, [r < 1, r > 1 ], [1, lambda i: (i/2)*(3-(i**2))])
In [9]: V
Out[9]: 
array([ 1.        ,  1.        ,  1.        ,  1.        ,  1.        ,
        1.        ,  1.        ,  0.98279633,  0.88700977,  0.6967488 ,
        0.40020411, -0.01443359, -0.55897361, -1.24522525, -2.08499781,
       -3.0901006 , -4.27234291, -5.64353404, -7.21548331, -9.        ])

But we don't need to use piecewise. Instead evaluate all values of r, and replace selected ones:

In [10]: V = (r/2)*(3 - (r**2))
In [12]: V[r<1] = 1
In [13]: V
Out[13]: 
array([ 1.        ,  1.        ,  1.        ,  1.        ,  1.        ,
        1.        ,  1.        ,  0.98279633,  0.88700977,  0.6967488 ,
        0.40020411, -0.01443359, -0.55897361, -1.24522525, -2.08499781,
       -3.0901006 , -4.27234291, -5.64353404, -7.21548331, -9.        ])

From the docs:

funclist : list of callables, f(x,*args,**kw), or scalars
        Each function is evaluated over `x` wherever its corresponding
        condition is True.  It should take a 1d array as input and give an 1d
        array or a scalar value as output.  If, instead of a callable,
        a scalar is provided then a constant function (``lambda x: scalar``) is
        assumed.

So the working piecewise is doing:

In [17]: fun = lambda i: (i/2)*(3-(i**2))
In [18]: fun(r[r>1])
Out[18]: 
array([ 0.98279633,  0.88700977,  0.6967488 ,  0.40020411, -0.01443359,
       -0.55897361, -1.24522525, -2.08499781, -3.0901006 , -4.27234291,
       -5.64353404, -7.21548331, -9.        ])

to create 13 values to put in V.

Sign up to request clarification or add additional context in comments.

Comments

0

Did you wanted something like this?

r = np.linspace(1, 10, 100)

V = np.piecewise(r, [r < 1, r > 0 ], [1, (r/2)*(3 - (r**2))])

#Graph of V r / k q vs. r/R for unitless quantities

figure()
plt.plot(r, V)
plt.xlabel('r / R') 
plt.ylabel('V r / k q') 
plt.title('Behavior of V(r) vs r')

ax = plt.gca()

ax.set_xticks([1])
  
ax.set_xticklabels(['R'])

plt.tick_params(left = False, right = False , labelleft = False)

plt.grid()

plt.show()

Graph

1 Comment

With that r, why use piecewise at all?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.