A variation of the proposed convolve routine is very fast: regular python took: 1.150214 sec. numpy mean slice took: 2.427513 sec. numpy convolve took: 0.546854 sec. numpy convolve noloop took: 0.058611 sec. Code: # mean of n values within an array import numpy, time def nmean(list,n): a = [] for i in range(1,len(list)+1): start = i-n divisor = n if start < 0: start = 0 divisor = i a.append(sum(list[start:i])/divisor) return a t = [1.0*i for i in range(1400)] start = time.clock() for x in range(100): reg = nmean(t,50) print "regular python took: %f sec."%(time.clock() - start) def numpy_nmean(list,n): a = numpy.empty(len(list),dtype=float) for i in range(1,len(list)+1): start = i-n if start < 0: start = 0 a[i-1] = list[start:i].mean(0) return a t = numpy.arange(0,1400,dtype=float) start = time.clock() for x in range(100): npm = numpy_nmean(t,50) print "numpy mean slice took: %f sec."%(time.clock() - start) def numpy_nmean_conv(list,n): b = numpy.ones(n,dtype=float) a = numpy.convolve(list,b,mode="full") for i in range(0,len(list)): if i < n : a[i] /= i + 1 else : a[i] /= n return a[:len(list)] t = numpy.arange(0,1400,dtype=float) start = time.clock() for x in range(100): npc = numpy_nmean_conv(t,50) print "numpy convolve took: %f sec."%(time.clock() - start) def numpy_nmean_conv_nl(list,n): b = numpy.ones(n,dtype=float) a = numpy.convolve(list,b,mode="full") for i in range(n): a[i] /= i + 1 a[n:] /= n return a[:len(list)] t = numpy.arange(0,1400,dtype=float) start = time.clock() for x in range(100): npn = numpy_nmean_conv_nl(t,50) print "numpy convolve noloop took: %f sec."%(time.clock() - start) numpy.testing.assert_equal(reg,npm) numpy.testing.assert_equal(reg,npc) numpy.testing.assert_equal(reg,npn) On 7/29/06, David Grant <davidgrant@gmail.com> wrote:
On 7/29/06, Charles R Harris <charlesr.harris@gmail.com> wrote:
Hmmm,
I rewrote the subroutine a bit.
def numpy_nmean(list,n): a = numpy.empty(len(list),dtype=float)
b = numpy.cumsum(list) for i in range(0,len(list)): if i < n : a[i] = b[i]/(i+1) else : a[i] = (b[i] - b[i-n])/(i+1) return a
and got
regular python took: 0.750000 sec. numpy took: 0.380000 sec.
I got rid of the for loop entirely. Usually this is the thing to do, at least this will always give speedups in Matlab and also in my limited experience with Numpy/Numeric:
def numpy_nmean2(list,n):
a = numpy.empty(len(list),dtype=float) b = numpy.cumsum(list) c = concatenate((b[n:],b[:n])) a[:n] = b[:n]/(i+1) a[n:] = (b[n:] - c[n:])/(i+1) return a
I got no noticeable speedup from doing this which I thought was pretty amazing. I even profiled all the functions, the original, the one written by Charles, and mine, using hotspot just to make sure nothing funny was going on. I guess plain old Python can be better than you'd expect in certain situtations.
-- David Grant