Numpy function operating on two ndarrays - python

Given two ndarrays a = np.asarray([[0,1,2],[3,4,5]]) and b = np.asarray([[6,7,8],[9,10,11]])I want to write a function that iterates over a and b, such that
[0,1,2] and [6,7,8] are considered
[3,4,5] and [9,10,11] are considered
An example would be a functionn that takes
[0,1,2] and [6,7,8] as an input and outputs 0*6+1*7+2*8 = 23
[3,4,5] and [9,10,11] as an input and outputs 3*9+4*10+5*11 = 122
-> (23,122)
Is there any way to do this efficiently in numpy?
My idea was to zip both arrays, however, this is not efficient.
Edit: I am looking for a way to apply a customizable function myfunc(x,y). In the previous example myfunc(x,y) corresponded to the multipication.

c = a * b
sum1 = c[0].sum()
sum2 = c[1].sum()
if you want the algorithmic way ( custom function )
a = np.asarray([[0,1,2],[3,4,5]])
b = np.asarray([[6,7,8],[9,10,11]])
for i in range(a.shape[0]) :
s = 0
for j in range(a.shape[1]) :
s = s + a[i][j]*b[i][j]
print(s)

import numpy as np
a = np.asarray([[0,1,2],[3,4,5]])
b = np.asarray([[6,7,8],[9,10,11]])
c = a*b
print(sum(c[0]),sum(c1))
ans->23,122

Don't need to use zip both array, you need to understand numpy package help you work well with matrix. So you need the basic knowledge about matrix, i recommend you learn from this link http://cs231n.github.io/python-numpy-tutorial/ , from cs231n of Stanford university.
This is a function can solve your problem:
import numpy as np
def interates(matrix_a, matrix_b):
product = matrix_a*matrix_b
return (np.sum(product,1))
The value product contain a new matrix with same shape of matrix_a and matrix_b, each element in there is the result of matrix_a[i][j] * matrix_b[i][j]with i and j run from 0 to matrix_a.shape[0]and matrix_a.shape[1].
Now check with your example
a = np.asarray([[0,1,2],[3,4,5]])
b = np.asarray([[6,7,8],[9,10,11]])
result = interates(a,b)
Print result
>> print(result)
>> [23 122]
If you want a tuple
>> result = tuple(result)
>> print(result)
>> (23, 122)

Related

Why operation on list is slower than operation on numpy array

I am doing a project on encrypting data using RSA algo and for that, I have taken a .wav file as an input and reading it by using wavfile and I can apply the key (3, 25777) but when I am applying the decryption key (16971,25777) it is giving wrong output like this:
The output I'm getting:
[[ 0 -25777]
[ 0 -25777]
[ 0 -25777]
...
[-25777 -25777]
[-15837 -15837]
[ -8621 1]]
output i want:
[[ 0 -1]
[ 2 -1]
[ 2 -3]
...
[-9 -5]
[-2 -2]
[-4 1]]
This was happening only with the decryption part of the array so I decided to convert the 2d array to a 2d list. After that, it is giving me the desired output but it is taking a lot of time to apply the keys to all the elements of the list(16min, in case of array it was 2sec). I don't understand why it is happening and if there is any other solution to this problem ?
here is the encryption and decryption part of the program:
#encryption
for i in range(0, tup[0]): #tup[0] is the no of rows
for j in range(0, tup[1]): #tup[1] is the no of cols
x = data[i][j]
x = ((pow(x,3)) % 25777) #applying the keys
data[i][j] = x #storing back the updated value
#decryption
data= data.tolist() #2d array to list of lists
for i1 in (range(len(data)):
for j1 in (range(len(data[i1]))):
x1 = data[i1][j1]
x1 = (pow(x1, 16971)%25777) #applying the keys
data[i1][j1] = x1
Looking forward to suggestions. Thank you.
The occurrence of something like pow(x1, 16971) should give you pause. This will for almost any integer x1 yield a result which a 64 bit int cannot hold. Which is the reason numpy gives the wrong result, because numpy uses 64 bit or 32 bit integers on the most common platforms. It is also the reason why plain python is slow, because while it can handle large integers this is costly.
A way around this is to apply the modulus in between multiplications, that way numbers remain small and can be readily handled by 64 bit arithmetic.
Here is a simple implementation:
def powmod(b, e, m):
b2 = b
res = 1
while e:
if e & 1:
res = (res * b2) % m
b2 = (b2*b2) % m
e >>= 1
return res
For example:
>>> powmod(2000, 16971, 25777)
10087
>>> (2000**16971)%25777
10087
>>> timeit(lambda: powmod(2000, 16971, 25777), number=100)
0.00031936285085976124
>>> timeit(lambda: (2000**16971)%25777, number=100)
0.255017823074013

Update values in numpy array without tedious for loops

I have a few arrays with data like this:
a = np.random.rand(3,3)
b = np.random.rand(3,3)
Using for loops I construct larger matrix
L = np.zeros((9,9))
for i in range(9):
for j in range(9):
L[i,j] = f(a,b,i,j) # values of L depends on values of a and b
Later in my program I will change a and b and I want my L array to change too. So the logic of my program looks like this (in pseudo code)
Create a
Create b
while True:
Create L using a and b
Do the stuff
Change a
Change b
In my program the size of L is large (10^6 x 10^6 and larger).
Constructing this L matrix again and again is tedious and slow process.
Instead of doing for loops again and again I would like just to update values of L matrix according to changed values of a and b. The structure of L is the same each time, the only difference is values of cells. Something like this:
a[0,0] = 2
b[0,0] = 2
L[3,5] = 2*a[0,0]*b[0,0]
L[3,5]
# >>> 8
a[0,0] = 3
b[0,0] = 1
# do some magic here
L[3,5]
>>> 6
Can something like this solve your problem ?
>>> a = 10
>>> b = 20
>>> def func():
# fetch the values of a and b
... return a+b
...
>>> lis = [func]
>>> lis[0]
<function func at 0x109f70730>
>>> lis[0]()
30
>>> a = 20
>>> lis[0]()
40
Basically every time you fetch the value by calling a function
that computes the latest value.

Numpy where conditional statement along axis 0

I have a 1D vector Zc containing n elements that are 2D arrays. I want to find the index of each 2D array that equals np.ones(Zc[i].shape).
a = np.zeros((5,5))
b = np.ones((5,5))*4
c = np.ones((5,5))
d = np.ones((5,5))*2
Zc = np.stack((a,b,c,d))
for i in range(len(Zc)):
a = np.ones(Zc[i].shape)
b = Zc[i]
if np.array_equal(a,b):
print(i)
else:
pass
Which returns 2. The code above works and returns the correct answer, but I want to know if there a vectorized way to achieve the same result?
Going off of hpaulj's comment:
>>> allones = (Zc == np.array(np.ones(Zc[i].shape))).all(axis=(1,2))
>>> np.where(allones)[0][0]
2

Cumulative integration of elements of numpy arrays

I would like to to the following type of integration:
Say I have 2 arrays
a = np.array[1,2,3,4]
b = np.array[2,4,6,8]
I know how to integrate these using something like:
c = scipy.integrate.simps(b, a)
where c = 15 for above data set.
What I would like to do is multiply the first elements of each array and add to new array called d, i.e. a[0]*b[0] then integrate the first 2 elements the arrays then the first 3 elements, etc. So eventually for this data set, I would get
d = [2 3 8 15]
I have tried a few things but no luck; I am pretty new to writing code.
If I have understood correctly what you need you could do the following:
import numpy as np
from scipy import integrate
a = np.array([2,4,6,8])
b = np.array([1,2,3,4])
d = np.empty_like(b)
d[0] = a[0] * b[0]
for i in range(2, len(a) + 1):
d[i-1] = integrate.simps(b[0:i], a[0:i])
print(d)

Matrix multiplication with numpy.einsum

I have the following two arrays with shape:
A = (d,w,l)
B = (d,q)
And I want to combine these into a 3d array with shape:
C = (q,w,l)
To be a bit more specific, in my case d (depth of the 3d array) is 2, and i'd first like to multiply all positions out of w * l in the upper layer of A (so d = 0) with the first value of B in the highest row (so d=0, q=0). For d=1 I do the same, and then sum the two so:
C_{q=0,w,l} = A_{d=0,w,l}*B_{d=0,q=0} + A_{d=1,w,l}*B_{d=1,q=0}
I wanted to calculate C by making use of numpy.einsum. I thought of the following code:
A = np.arange(100).reshape(2,10,5)
B = np.arange(18).reshape(2,9)
C = np.einsum('ijk,i -> mjk',A,B)
Where ijk refers to 2,10,5 and mjk refers to 9,10,5. However I get an error. Is there some way to perform this multiplication with numpy einsum?
Thanks
Your shapes A = (d,w,l), B = (d,q), C = (q,w,l) practically write the einsum expression
C=np.einsum('dwl,dq->qwl',A,B)
which I can test with
In [457]: np.allclose(A[0,:,:]*B[0,0]+A[1,:,:]*B[1,0],C[0,:,:])
Out[457]: True

Categories