Sum 2-D arrays in Python - python

I have two 2-D arrays, and I tried to sum element-wise
A = array([[-0.31326169, -0., -3.23995333],
[-0.26328247, -0., -0.64439666]])
B = array([[-0 , -0.28733533, -0.],
[-0 , -2.12692801, -0]])
sum(A + B)
array([-0.57654415, -2.41426334, -3.88434999])
Why does it result in a 1-D array?

What you are looking for is numpy.add
import numpy as np
arr1 = np.array([[-0.31326169, -0., -3.23995333],[-0.26328247, -0., -0.64439666]])
arr2 = np.array([[-0., -0.28733533, -0.],[-0., -2.12692801, -0.]])
arr3=np.add(arr1,arr2)
print(arr3)
Output
[[-0.31326169 -0.28733533 -3.23995333]
[-0.26328247 -2.12692801 -0.64439666]]

This happens because A + B is a 2 by 3 array, and it's then summed using the built-in sum function (np.sum would've returned a single number).
__builtins__.sum will iterate over the given array, and the iteration happens to be row-wise, so individual rows will be added up (I called your arrays X and Y):
>>> X + Y
array([[-0.31326169, -0.28733533, -3.23995333],
[-0.26328247, -2.12692801, -0.64439666]])
Then, sum(X + Y) will do the following:
__sum = 0
for row in (X + Y):
__sum += row
return __sum
So, individual rows will be summed:
>>> X + Y
array([[-0.31326169, -0.28733533, -3.23995333],
[-0.26328247, -2.12692801, -0.64439666]])
>>> _[0] + _[1]
array([-0.57654416, -2.41426334, -3.88434999])
If you want to sum X and Y element-wise, then... just sum them: result = X + Y.

Related

Insert calculated values between consecutive values in array

Let's say I have a simple array, like this one:
import numpy as np
a = np.array([1,2,3])
Which returns me, obviously:
array([1, 2, 3])
I'm trying to add calculated values between consecutive values in this array. The calculation should return me n equally spaced values between it's bounds.
To express myself in numbers, let's say I want to add 1 value between each pair of consecutive values, so the function should return me a array like this:
array([1, 1.5, 2, 2.5, 3])
Another example, now with 2 values between each pair:
array([1, 1.33, 1.66, 2, 2.33, 2.66, 3])
I know the logic and I can create myself a function which will do the work, but I feel numpy has specific functions that would make my code so much cleaner!
If your array is
import numpy as np
n = 2
a = np.array([1,2,5])
new_size = a.size + (a.size - 1) * n
x = np.linspace(a.min(), a.max(), new_size)
xp = np.linspace(a.min(), a.max(), a.size)
fp = a
result = np.interp(x, xp, fp)
returns: array([1. , 1.33333333, 1.66666667, 2. , 2.66666667, 3.33333333, 4. ])
If your array is always evenly spaced, you can just use
new_size = a.size + (a.size - 1) * n
result = np.linspace(a.min(), a.max(), new_size)
Using linspace should do the trick:
a = np.array([1,2,3])
n = 1
temps = []
for i in range(1, len(a)):
temps.append(np.linspace(a[i-1], a[i], num=n+1, endpoint=False))
# Add last final ending point
temps.append(np.array([a[-1]]))
new_a = np.concatenate(temps)
print(new_a)
Try with np.arange:
a = np.array([1,2,3])
n = 2
print(np.arange(a.min(), a.max(), 1 / (n + 1)))
Output:
[1. 1.33333333 1.66666667 2. 2.33333333 2.66666667]

Python- Numpy array in function with conditions

I have a numpy array (say xs), for which I am writing a function to create another array (say ys), which has the same values as of xs until the first half of xs and two times of xs in the remaining half. for example, if xs=[0,1,2,3,4,5], the required output is [0,1,2,6,8,10]
I wrote the following function:
import numpy as np
xs=np.arange(0,6,1)
def step(xs):
ys1=np.array([]);ys2=np.array([])
if xs.all() <=2:
ys1=xs
else:
ys2=xs*2
return np.concatenate((ys1,ys2))
print(xs,step(xs))
Which produces output: `array([0., 1., 2., 3., 4., 5.]), ie the second condition is not executed. Does anybody know how to fix it? Thanks in advance.
You can use vectorised operations instead of Python-level iteration. With the below method, we first copy the array and then multiply the second half of the array by 2.
import numpy as np
xs = np.arange(0,6,1)
def step(xs):
arr = xs.copy()
arr[int(len(arr)/2):] *= 2
return arr
print(xs, step(xs))
[0 1 2 3 4 5] [ 0 1 2 6 8 10]
import numpy as np
xs=np.arange(0,6,1)
def f(a):
it = np.nditer([a, None])
for x, y in it:
y[...] = x if x <= 2 else x * 2
return it.operands[1]
print(f(xs))
[ 0 1 2 6 8 10]
Sorry, I did not find your bug, but I felt it can be implemented differently.

Summing array values by repeating index for an array

I want to sum the values in vals into elements of a smaller array a specified in an index list idx.
import numpy as np
a = np.zeros((1,3))
vals = np.array([1,2,3,4])
idx = np.array([0,1,2,2])
a[0,idx] += vals
This produces the result [[ 1. 2. 4.]] but I want the result [[ 1. 2. 7.]], because it should add the 3 from vals and 4 from vals into the 2nd element of a.
I can achieve what I want with:
import numpy as np
a = np.zeros((1,3))
vals = np.array([1,2,3,4])
idx = np.array([0,1,2,2])
for i in np.unique(idx):
fidx = (idx==i).astype(int)
psum = (vals * fidx).sum()
a[0,i] = psum
print(a)
Is there a way to do this with numpy without using a for loop?
Possible with np.add.at as long as the shapes align, i.e., a will need to be 1D here.
a = a.squeeze()
np.add.at(a, idx, vals)
a
array([1., 2., 7.])

How to scan through all the elements of a matrix with theano?

TL;DR:
What is the theano.scan equivalent of:
M = np.arange(9).reshape(3, 3)
for i in range(M.shape[0]):
for j in range(M.shape[1]):
M[i, j] += 5
M
possibly (if doable) without using nested scans?
Note that this question does not want to be specifically about how to apply an operation elementwise to a matrix, but more generally on how to implement with theano.scan a nested looping construct like the above.
Long version:
theano.scan (or equivalently in this case, theano.map) allows to map a function looping through multiple indices, by simply providing a sequence of elements to the sequences arguments, with something like
import theano
import theano.tensor as T
M = T.dmatrix('M')
def map_func(i, j, matrix):
return matrix[i, j] + i * j
results, updates = theano.scan(map_func,
sequences=[T.arange(M.shape[0]), T.arange(M.shape[1])],
non_sequences=[M])
f = theano.function(inputs=[M], outputs=results)
f(np.arange(9).reshape(3, 3))
#
which is roughly equivalent to a python loop of the form:
M = np.arange(9).reshape(3, 3)
for i, j in zip(np.arange(M.shape[0]), np.arange(M.shape[1])):
M[i, j] += 5
M
which increases by 5 all the elements in the diagonal of M.
But what if I want to find the theano.scan equivalent of:
M = np.arange(9).reshape(3, 3)
for i in range(M.shape[0]):
for j in range(M.shape[1]):
M[i, j] += 5
M
possibly without nesting scan?
One way is of course to flatten the matrix, scan through the flattened elements, and then reshape it to the original shape, with something like
import theano
import theano.tensor as T
M = T.dmatrix('M')
def map_func(i, X):
return X[i] + .5
M_flat = T.flatten(M)
results, updates = theano.map(map_func,
sequences=T.arange(M.shape[0] * M.shape[1]),
non_sequences=M_flat)
final_M = T.reshape(results, M.shape)
f = theano.function([M], final_M)
f([[1, 2], [3, 4]])
but is there a better way that doesn't involve explicitly flattening and reshaping the matrix?
Here is an example on how this kind of thing can be achieve using nested theano.scan calls.
In this example we add the number 3.141 to every element of a matrix, effectively simulating in a convoluted way the output of H + 3.141:
H = T.dmatrix('H')
def fn2(col, row, matrix):
return matrix[row, col] + 3.141
def fn(row, matrix):
res, updates = theano.scan(fn=fn2,
sequences=T.arange(matrix.shape[1]),
non_sequences=[row, matrix])
return res
results, updates = theano.scan(fn=fn,
sequences=T.arange(H.shape[0]),
non_sequences=[H])
f = theano.function([H], results)
f([[0, 1], [2, 3]])
# array([[ 3.141, 4.141],
# [ 5.141, 6.141]])
As another example, let us add to each element of a matrix the product of its row and column indices:
H = T.dmatrix('H')
def fn2(col, row, matrix):
return matrix[row, col] + row * col
def fn(row, matrix):
res, updates = theano.scan(fn=fn2,
sequences=T.arange(matrix.shape[1]),
non_sequences=[row, matrix])
return res
results, updates = theano.scan(fn=fn,
sequences=T.arange(H.shape[0]),
non_sequences=[H])
f = theano.function([H], results)
f(np.arange(9).reshape(3, 3))
# Out[2]:array([[ 0., 1., 2.],
# [ 3., 5., 7.],
# [ 6., 9., 12.]])

how to use sparse vectors and matrices in Python?

I am trying to do something very simple, but confused by the abundance of information about sparse matrices and vectors in Python.
I want to create two vectors, x and y, one of length 5 and one of length 6, being sparse. Then I want to set one coordinate in each one of them. Then I want to create a matrix A, sparse, which is 5 x 6 and add to it the outer product between x and y. I then want to do SVD on that A.
Here is what I tried, and it goes wrong in many ways.
from scipy import sparse;
import numpy as np;
import scipy.sparse.linalg as ssl;
x = sparse.bsr_matrix(np.zeros(5));
x[1] = 1;
y = sparse.bsr_matrix(np.zeros(6));
y[1] = 2;
A = sparse.coo_matrix(5, 6);
A = A + np.outer(x,y.transpose())
svdresult = ssl.svds(A,1);
At first, you should determine data you want to store in sparse matrix before constructing it. Otherwise you should use sparse.csc_matrix or sparse.csr_matrix instead. Then you can assign or change data like this:
x[0, 1] = 1
At second, outer product of vectors x and y is equivalent to x.transpose() * y.
Here is working code:
from scipy import sparse
import numpy as np
import scipy.sparse.linalg as ssl
x = np.zeros(5)
x[1] = 1
x_bsr = sparse.bsr_matrix(x)
y = np.zeros(6)
y[1] = 2
y_bsr = sparse.bsr_matrix(y)
A = sparse.coo_matrix((5, 6)) # Sparse matrix 5 x 6
B = x_bsr.transpose().dot(y_bsr) # Outer product of x and y
svdresult = ssl.svds((A + B), 1)
Output:
(array([[ 5.55111512e-17],
[ -1.00000000e+00],
[ 0.00000000e+00],
[ -2.77555756e-17],
[ 1.11022302e-16]]), array([ 2.]), array([[ 0., -1., 0., 0., 0., 0.]]))

Categories