mohammed awni
mohammed awni

Reputation: 168

Series sum in python

Is there is a built-in function in python, numpy or one of its libraries can get sum of series like this one:

list1 = [2,3,4]
list2 = [3,3,3]

enter image description here

where x and y are lists and L is the length of x or y.

Lastly if there is no built-in function do that, I tried another code like :

Total = sum ((i for i in list1) * (j for j in list2))

Sure, it doesn't work but I need something near that or near this one:

Total = sum (i * j for i in list1 and j in list2 )

Note : I can build my own function to do that but I am looking for a simple, fast or built-in one, so please don't give me your own function.

Edit : I want general form to do that so I can use this form when there are as an example Log(n) or another kind of math in the series.

enter image description here

Upvotes: 4

Views: 6665

Answers (5)

Copperfield
Copperfield

Reputation: 8510

for build-in you can use zip to group together elements in the same index position

list1 = [2,3,4]
list2 = [3,3,3]
result = sum( x*y for x,y in zip(list1, list2) )

About the edit

A buil-in version would be

from math import log
result = sum( log(i)*y for i,y in enumerate(list1,1) )

a more generalized version would be

enter image description here

import operator
def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul):
    return sum(map(mul, vec1, vec2))    

where you can provide whatever function you like for any of its part, then the first one is

result = dotproduct(list1,list2)

and the second is could be

result = dotproduct(range(1,len(list1)+1),list1, mul=lambda i,x:log(i)*x )
#                        ^ the i                    ^ how to operate

or

result = dotproduct(map(log,range(1,len(list1)+1) ), list1 )
#                           ^ the log i

the point being that you calculate the second vector accordingly

with numpy is more easy

import numpy as np
logi = np.log(np.arange(1,len(list1)+1)
result = np.dot(logi,list1)

which again boils down to calculate the parts accordingly


you can also make such that instead of receiving 2 vectors/lists it only work with one and receive a function that work in the element and its index

enter image description here

def sum_serie(vect, fun = lambda i,x:x, i_star=0): #with that fun, is like the regular sum
    return sum( fun(i,x) for i,x in enumerate(vect, i_star) )

and use it as

result = sum_serie( list1, lambda i,x:log(i)*x, 1)

from the comments, if I get it right, then something like this

from itertools import islice
def sum_serie(vect, *slice_arg, fun = lambda x:x): #with that fun, is like the regular sum
    """sum_serie(vect, [start,]stop[,step], fun = lambda x:x)"""
    if not slice_arg:
        slice_arg = (0,None,None)
    return sum( fun(x) for x in islice(vect, *slice_arg) )

or with enumerate as before

from itertools import islice
def sum_serie_i(vect, *slice_arg, fun = lambda i,x:x): #with that fun, is like the regular sum
    if not slice_arg:
        slice_arg = (0,None,None)
    return sum( fun(i,x) for i,x in islice(enumerate(vect), *slice_arg) )

and use, for example as

sum_serie( x, 0, 100, 2, fun=lambda xi: c*xi) #for arbitrary constant c
sum_serie_i( x, 0, 100, 2, fun=lambda i,xi: log(i)*xi)

Note: this way it accept the serie/iterable/whatever and at most 3 positional argument with the same meaning as those from range

Note 2: that is for PY3 which make fun a key-word only argument, in python 2 the same effect is accomplished with

def sum_serie_i(vect, *slice_arg, **kargv): 
    fun = kargv.get('fun', lambda i,x:x) #with that fun, is like the regular sum
    if not slice_arg:
        slice_arg = (0,None,None)
    return sum( fun(i,x) for i,x in islice(enumerate(vect), *slice_arg) )

Upvotes: 5

piRSquared
piRSquared

Reputation: 294218

These all do the same thing

np.einsum

np.einsum('i,i', list1, list2)

np.inner

np.inner(list1, list2)

np.dot

np.dot(list1, list2)

All yield 27

For bigger arrays, np.einsum starts to see a performance boost

enter image description here

Upvotes: 1

kmario23
kmario23

Reputation: 61305

Use * operator and sum it along 0th axis.

In [48]: a
Out[48]: array([0, 1, 2, 3, 4])

In [49]: b
Out[49]: array([5, 6, 7, 8, 9])

In [50]: a*b
Out[50]: array([ 0,  6, 14, 24, 36])

In [51]: np.sum(a*b, axis=0)
Out[51]: 80

But, you should really be using the much cooler and ultra-fast np.inner()

# `a, b` can also be python lists
In [65]: np.inner(a, b)
Out[65]: 80

Upvotes: 0

MSeifert
MSeifert

Reputation: 152587

The mathematical operators with numpy arrays do element-wise operations, so you can use:

import numpy as np
np.sum(np.multiply(list1, list2))
# or np.sum(list1 * list2)  if any of list1/list2 is a numpy array

or in the second case:

logi = np.log(np.arange(1, len(x)))  # or np.log10, not sure which one you mean
np.sum(np.multiply(logi, x[1:]))

as already mentioned np.sum(np.multiply()) is just a dotproduct, so you could also use @ (at least with python 3.5+, otherwise use np.dot):

np.asarray(list1) @ list2  # if list1/list2 are numpy arrays you don't need the np.asarray

Upvotes: 1

user2357112
user2357112

Reputation: 280227

That's literally just a dot product:

result = numpy.dot(list1, list2)

Note that if you're using NumPy, you shouldn't be using lists to represent your matrices and vectors. NumPy arrays are much more efficient and convenient for that.

Upvotes: 9

Related Questions