Search code examples
pythonpython-3.xnumpyloopsmath

Problem execute calculations in a nested loop. TypeError: 'numpy.float64' object is not iterable


I'm trying to calculate the sum of squared errors and i'm using a nested loop.

enter image description here

I'm new to Python and i apologize, but i encounter the error:

  File "...", line 13, in <module>
    for y in values_subtraction_mean:
TypeError: 'numpy.float64' object is not iterable

The problem is with the second loop, when i have to calculate result in: for y in values_subtraction_mean: result = sum(math.sqrt(y))

In the second loop, it should show all values of values_subtraction_mean, so it should show 2.2, -0.8, 0.2, 1.2, -2.8. Next for each value above, a sqrt should be calculated and get 4.84, 0.64, 0.04, 1.44, 7.84. In the end you have to sum all these numbers and get 14.8

What am I doing wrong?

from numpy import mean
import math

values = [5, 2, 3, 4, 0]

mean = mean(values)

for x in values:
  values_subtraction_mean = x - mean
  print(values_subtraction_mean)
  #2.2, -0.8, 0.2, 1.2, -2.8

  for y in values_subtraction_mean:
    result = sum(math.sqrt(y))
    print(result)
    #sqrt: 4.84, 0.64, 0.04, 1.44, 7.84
    #sum and result: 14.8

I tried using this, but it doesn't solve the problem:

import numpy as np
values = np.array([5, 2, 3, 4, 0])

I tried not using numpy, calculating the mean with: sum(values) / len(values), but it doesn't work either and i get error:

TypeError: 'float' object is not iterable


Solution

  • You seem to have problems understanding basic python iteration, let alone numpy. So lets look at your code in detail

    In [1]: import numpy as np
       ...: import math
       ...: 
       ...: values = [5, 2, 3, 4, 0]
       ...: 
       ...: mean = np.mean(values)
       ...: 
       ...: for x in values:
       ...:   values_subtraction_mean = x - mean
       ...:   print(values_subtraction_mean)
       ...: 
       ...:   for y in values_subtraction_mean:
       ...:     result = sum(math.sqrt(y))
       ...:     print(result)
       ...: 
    2.2
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    Cell In[1], line 12
          9 values_subtraction_mean = x - mean
         10 print(values_subtraction_mean)
    ---> 12 for y in values_subtraction_mean:
         13   result = sum(math.sqrt(y))
         14   print(result)
    
    TypeError: 'numpy.float64' object is not iterable
    

    So the error is in that for y in values...: line. The for x in values: works because values is a list. Inside that loop it calculates the mean (with a numpy mean function):

    In [2]: mean
    Out[2]: 2.8
    
    In [3]: type(mean)
    Out[3]: numpy.float64
    
    In [4]: values_subtraction_mean
    Out[4]: 2.2
    
    In [5]: x
    Out[5]: 5
    

    You substracted the mean from one element of the list, and then tried to iterate on that value. The y loop is nested inside the x loop. Plus the x loop isn't accumulating any of those x-mean values.

    The following line will have problems as well

    sum(math.sqrt(y))
    

    math functions only work on scalars, not lists or arrays. But python sum requires an iterable (e.g. a list). So I don't quite get what you intend here.

    Corrected iteration - sort of

    The standard way to iterate on a list is to append the results to a list. Changing your code:

    In [9]: values = [5, 2, 3, 4, 0]
       ...: 
       ...: mean = np.mean(values)
       ...: values_sublist = []
       ...: for x in values:
       ...:   values_sublist.append(x - mean)
       ...: print(values_sublist)
       ...: result = []
       ...: for y in values_sublist:
       ...:     result.append(math.sqrt(y))
       ...: print(result)
    [2.2, -0.7999999999999998, 0.20000000000000018, 1.2000000000000002, -2.8]
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    Cell In[9], line 10
          8 result = []
          9 for y in values_sublist:
    ---> 10     result.append(math.sqrt(y))
         11 print(result)
    
    ValueError: math domain error
    

    values_sublist is all the list values minus their mean. So the y loop works. But it runs into another problem - it can't take the sqrt of a negative number!

    numpy version

    In [10]: values
    Out[10]: [5, 2, 3, 4, 0]
    
    In [11]: mean=np.mean(values)
    
    In [12]: mean
    Out[12]: 2.8
    
    In [13]: np.array(values)-mean
    Out[13]: array([ 2.2, -0.8,  0.2,  1.2, -2.8])
    
    In [14]: np.sqrt(np.array(values)-mean)
    C:\Users\14256\AppData\Local\Temp\ipykernel_8020\509743582.py:1: RuntimeWarning: invalid value encountered in sqrt
      np.sqrt(np.array(values)-mean)
    Out[14]: array([1.4832397 ,        nan, 0.4472136 , 1.09544512,        nan])
    

    It's possible to do this without the python loops, if values is a numpy array. Now the negative values produce a nan value, and a warning. There's no point to doing the sum on the array with nan.

    complex values

    We can deal with the sqrt issue by making values a complex dtype array:

    In [15]: values_c = np.array(values,complex); values_c
    Out[15]: array([5.+0.j, 2.+0.j, 3.+0.j, 4.+0.j, 0.+0.j])
    
    In [16]: np.mean(values_c)
    Out[16]: (2.8000000000000003+0j)
    
    In [17]: values_c - np.mean(values_c)
    Out[17]: array([ 2.2+0.j, -0.8+0.j,  0.2+0.j,  1.2+0.j, -2.8+0.j])
    
    In [18]: np.sqrt(values_c - np.mean(values_c))
    Out[18]: 
    array([1.4832397 +0.j        , 0.        +0.89442719j,
           0.4472136 +0.j        , 1.09544512+0.j        ,
           0.        +1.67332005j])
    
    In [19]: np.sum(_)
    Out[19]: (3.0258984079294224+2.5677472440680673j)
    

    Though I'm not sure that's what you need.

    square instead of sqrt

    But wait, the "sqrt" values that you want are actually the square values, not square root.

    In [20]: values = [5, 2, 3, 4, 0]
        ...: mean = np.mean(values)
        ...: values_sublist = []
        ...: for x in values:
        ...:   values_sublist.append(x - mean)
        ...: print(values_sublist)
        ...: result = []
        ...: for y in values_sublist:
        ...:     result.append(y**2)
        ...: print(result); print(sum(result))
    [2.2, -0.7999999999999998, 0.20000000000000018, 1.2000000000000002, -2.8]
    [4.840000000000001, 0.6399999999999997, 0.04000000000000007, 1.4400000000000004, 7.839999999999999]
    14.8
    

    Now your two loops work just fine.

    And written as one numpy expression:

    In [21]: np.sum((np.array(values)-np.mean(values))**2)
    Out[21]: 14.8
    

    We could also use a list comprehension in place of the for loops - though we still have to use np.mean, or a loop equivalent. So it isn't a pure list calculation:

    In [22]: values
    Out[22]: [5, 2, 3, 4, 0]
    
    In [23]: mean
    Out[23]: 2.8
    
    In [24]: sum((x-mean)**2 for x in values)
    Out[24]: 14.8
    

    That sqrt and complex code may be a distraction, but I'll leave that in because I think it may be instructive. It's part of debugging your code.