Question

I have an array where discreet sinewave values are recorded and stored. I want to find the max and min of the waveform. Since the sinewave data is recorded voltages using a DAQ, there will be some noise, so I want to do a weighted average. Assuming self.yArray contains my sinewave values, here is my code so far:

filterarray = []
filtersize = 2
length = len(self.yArray)
for x in range (0, length-(filtersize+1)):
   for y in range (0,filtersize):
      summation = sum(self.yArray[x+y])
      ave = summation/filtersize
      filterarray.append(ave)

My issue seems to be in the second for loop, where depending on my averaging window size (filtersize), I want to sum up the values in the window to take the average of them. I receive an error saying:

summation = sum(self.yArray[x+y])
TypeError: 'float' object is not iterable

I am an EE with very little experience in programming, so any help would be greatly appreciated!

Was it helpful?

Solution 2

self.yArray[x+y] is returning a single item out of the self.yArray list. If you are trying to get a subset of the yArray, you can use the slice operator instead:

summation = sum(self.yArray[x:y])

to return an iterable that the sum builtin can use.

A bit more information about python slices can be found here (scroll down to the "Sequences" section): http://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy

OTHER TIPS

The other answers correctly describe your error, but this type of problem really calls out for using numpy. Numpy will run faster, be more memory efficient, and is more expressive and convenient for this type of problem. Here's an example:

import numpy as np
import matplotlib.pyplot as plt

# make a sine wave with noise
times = np.arange(0, 10*np.pi, .01)
noise = .1*np.random.ranf(len(times))
wfm = np.sin(times) + noise

# smoothing it with a running average in one line using a convolution
#    using a convolution, you could also easily smooth with other filters
#    like a Gaussian, etc.
n_ave = 20
smoothed = np.convolve(wfm, np.ones(n_ave)/n_ave, mode='same')

plt.plot(times, wfm, times, -.5+smoothed)
plt.show()

enter image description here

If you don't want to use numpy, it should also be noted that there's a logical error in your program that results in the TypeError. The problem is that in the line

summation = sum(self.yArray[x+y])

you're using sum within the loop where your also calculating the sum. So either you need to use sum without the loop, or loop through the array and add up all the elements, but not both (and it's doing both, ie, applying sum to the indexed array element, that leads to the error in the first place). That is, here are two solutions:

filterarray = []
filtersize = 2
length = len(self.yArray)
for x in range (0, length-(filtersize+1)):
    summation = sum(self.yArray[x:x+filtersize]) # sum over section of array
    ave = summation/filtersize
    filterarray.append(ave)

or

filterarray = []
filtersize = 2
length = len(self.yArray)
for x in range (0, length-(filtersize+1)):
    summation = 0.
    for y in range (0,filtersize):
        summation = self.yArray[x+y]
    ave = summation/filtersize
    filterarray.append(ave)

You could use numpy, like:

import numpy
filtersize = 2
ysums = numpy.cumsum(numpy.array(self.yArray, dtype=float))
ylags = numpy.roll(ysums, filtersize)
ylags[0:filtersize] = 0.0
moving_avg = (ysums - ylags) / filtersize

Your original code attempts to call sum on the float value stored at yArray[x+y], where x+y is evaluating to some integer representing the index of that float value.

Try: summation = sum(self.yArray[x:y])

Indeed numpy is the way to go. One of the nice features of python is list comprehensions, allowing you to do away with the typical nested for loop constructs. Here goes an example, for your particular problem...

import numpy as np
step=2
res=[np.sum(myarr[i:i+step],dtype=np.float)/step for i in range(len(myarr)-step+1)]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top