# Numpy error when computing scores based on percentiles

I want to calculate scores in one field based on the percentile (in steps of 10) the row falls into in another field. I found a solution here (Calculating Percentiles in ArcMap?) that I tried out, but I now get the error:

``````unsupported operand type(s) for *: 'numpy.ndarray' and 'numpy.ndarray'
``````

My code looks as follows:

``````input = "Buffer"
arr = arcpy.da.FeatureClassToNumPyArray(input, ('Shape_Area'))

p1 = np.percentile(arr, 10)
p2 = np.percentile(arr, 20)
p3 = np.percentile(arr, 30)
p4 = np.percentile(arr, 40)
p5 = np.percentile(arr, 50)
p6 = np.percentile(arr, 60)
p7 = np.percentile(arr, 70)
p8 = np.percentile(arr, 80)
p9 = np.percentile(arr, 90)
p10 = np.percentile(arr, 100)
#use cursor to update the new rank field
with arcpy.da.UpdateCursor(input , ['Shape_Area','ConS']) as cursor:
for row in cursor:
if row < p1:
row = 0.1  #rank 0
elif p1 <= row and row < p2:
row = 0.2
elif p2 <= row and row < p3:
row = 0.3
elif p3 <= row and row < p4:
row = 0.4
elif p4 <= row and row < p5:
row = 0.5
elif p5 <= row and row < p6:
row = 0.6
elif p6 <= row and row < p7:
row = 0.7
elif p7 <= row and row < p8:
row = 0.8
elif p9 <= row and row < p10:
row = 0.9
else:
row = 1

cursor.updateRow(row)
``````

When searching on the internet I found that the problem behind this error often lies in the values being strings rather than floats or integers so I edited my code to read:

``````p1 = np.percentile(arr, 10, np.float)
p2 = np.percentile(arr, 20, np.float)
p3 = np.percentile(arr, 30, np.float)
``````

And now I got the error message:

``````'type' object is not iterable
``````

What can I do to solve this issue, or is there maybe another way to calculate the scores?

• See documentation for `numpy.percentile` here. You are providing a type (`np.float`) as a parameter where the parameter needs to be the axis along which the percentiles are computed. Oct 22, 2015 at 8:51
• Ok, that explains why the second version does not work, but what can I do to get the first version to work? Oct 22, 2015 at 8:54
• Can you provide a sample of some of the values in your variable `arr`? Oct 22, 2015 at 8:56
• This would be an example: >>> print(arr) `[(39710.930139345284,) (32032.62901900672,) (13822.309180032586,) ..., (33956.1676006977,) (35127.24443114165,) (23696.81216139415,)]` Oct 22, 2015 at 9:43
• Can you confirm that for the results of `numpy.percentile`, for example `p1`, is a single value and that all of the records in your feature class have a value for `'Shape_Area'`? Oct 22, 2015 at 9:48

The issue here is that the values in `arr` are tuples `(value_one, value_two)` with the first item only containing a value as is shown in your comment explaining the values in `arr`:

`[(39710.930139345284,) (32032.62901900672,) (13822.309180032586,) ..., (33956.1676006977,) (35127.24443114165,) (23696.81216139415,)]`

In your case you only want to use the first item of the tuple because the second item does not have a value. To do this use list comprehension:

``````correct_array = [float(x) for x in numpy.ndarray.flatten(arr)]
``````

In a nutshell this will flatten `arr` into a 1d array and convert the first element of each tuple, `x`, into a float during the process. With the new array, that only contains the values of the first item of each tuple, you can run your code as usual:

``````p1 = numpy.percentile(correct_array, 50)
``````

In this case, converting to a 1d array is inconsequential because you are only interested in the values and not there specific order or location in the array. This should produce the percentile values that you are looking for.

• That gives a new error message: `cannot convert to a float; scalar object is not a number` Oct 22, 2015 at 11:02
• @sdots I have updated the answer to address this new error message. Does the updated answer fix the issue for you? Oct 22, 2015 at 19:15
• Sorry, I was gone over the weekend, yes that seems to have worked! Thanks :) Oct 27, 2015 at 9:33

As an alternate to flattening the array, could also just access a single field of the array.

If you substitute this:

`arr = arcpy.da.FeatureClassToNumPyArray(input, ('Shape_Area'))['Shape_Area']`

in place of:

`arr = arcpy.da.FeatureClassToNumPyArray(input, ('Shape_Area'))`

Should be more efficient, although it may not matter much depending on the size of your data.