numpy how to do bulk operation on every element of the array - python

I've a numpy array
[
[1,5,6],
[10,12,20]
]
I want to do an operation on every element of the array that, takes the current element value and does an operation. A sort of bulk operation like the np.square function.
i.e. x = (x + 1) * 2
the result would be:
[
[4,12,14],
[22,26,42]
]
I know I can do a for loop for every element and apply the operation but I want more compact syntax.

You can use numpy:
import numpy as np
lst = [
[1, 5, 6],
[10, 12, 20]
]
lst = np.array(lst)
lst = (lst + 1) * 2
print(lst)
Which outputs, as desired:
[[ 4 12 14]
[22 26 42]]
if at the end you want it to be a list you may convert it back, but np arrays are great.

Solution using numpy vectorize:
# define numpy array
arr = np.array([
[1,5,6],
[10,12,20]
])
# create function
func = np.vectorize(lambda x: (x + 1) * 2)
# apply function to array
func(arr)

Related

How to broadcast sum of list of list?

How to broadcast the sum of list of list in an efficient way?
below is a working code, but its not quite efficient when list1 has nth value like 30 elements.
Any improvement on this?
from numpy import sum
import numpy as np
list1 = [[4,8],[8,16]]
list2 = [2]
elemSum=[sum(list1[0]),sum(list1[1])]
print((np.array(elemSum)/np.array(list2)))
prints:
[ 6. 12.] # expected output
I want a single line like this below , eliminating the declaration of variable elemSum, but it yields incorrect output since it sums 2 elements to 1
print(sum(np.array(list1)/np.array(list2)))
prints:
18.0 # not expected it sums 2 elements to 1
numpy.sum takes an optional axis argument, which can be used for partial sums along a single axis:
>>> list1 = np.array([[4,8],[8,16]])
>>> list2 = np.array([2])
>>> np.sum(list1)
36
>>> np.sum(list1, axis=1)
array([12, 24])
>>> np.sum(list1, axis=1) / list2
array([ 6., 12.])
Just use numpy the entire time, don't mess with lists if you want arrays:
list1 = [[4,8],[8,16]]
list2 = [2]
import numpy as np
arr1 = np.array(list1)
arr2 = np.array(list2)
Then simply:
result = arr1.sum(axis=1) / arr2

Array Prints like List but its a single integer in variable explorer? Why?

When ı print out the following code Q is prints like it suppose to be (3 5 7 9) sum of the numbers with the next one. but in the variable explorer its a single integer ı want to get the result Q as an array like
Q = [3, 5, 7, 9]
import numpy as np
A = [1, 2, 3, 4, 5]
for i in range(0,4):
Q = np.array(A[i]+A[i+1])
print(Q)
for i in range(0,4):
Q = []
Q.append(Q[i] + A[i]+A[i+1])
print(Q)
This also doesnt work
Currently you're just re-declaring Q each time and it's never added to some collection of values
Instead, start with an empty list (or perhaps a numpy array in your case) and outside of your loop and append the values to it at each loop cycle
Q is a numpy array, but it's not what you're expecting!
It has no dimensions and only references a single value
>>> type(Q)
<class 'numpy.ndarray'>
>>> print(repr(Q))
array(9)
>>> import numpy as np
>>> A = [1, 2, 3, 4, 5]
>>> Q = np.array([], dtype=np.uint8)
>>> for i in range(4):
... Q = np.append(Q, A[i]+A[i+1]) # reassign each time for np
...
>>> print(Q)
[3 5 7 9]
Note that numpy arrays should be reassigned via np.append, while a normal python list has a .append() method (which does not return the list, but directly appends to it)
>>> l = ['a', 'b', 'c'] # start with a list of values
>>> l.append('d') # use the append method
>>> l # display resulting list
['a', 'b', 'c', 'd']
If you're not forced to use a numpy array to begin with, this can be done with a list comprehension
The resulting list can also be made into a numpy array afterwards
>>> [(x + x + 1) for x in range(1, 5)]
[3, 5, 7, 9]
All together with simplified math
>>> np.array([x*2+3 for x in range(4)])
array([3, 5, 7, 9])
If you want to use Numpy, then use Numpy. Start with a Numpy array (one-dimensional, containing the values), which looks like this:
A = np.array([1, 2, 3, 4, 5])
(Yes, you initialize it from the list).
Or you can create that kind of patterned data using Numpy's built-in tool:
A = np.arange(1, 6) # it works similarly to the built-in `range` type,
# but it does create an actual array.
Now we can get the values to use on the left-hand and right-hand sides of the addition:
# You can slice one-dimensional Numpy arrays just like you would lists.
# With more dimensions, you can slice in each dimension.
X = A[:-1]
Y = A[1:]
And add the values together element-wise:
Q = X + Y # yes, really that simple!
And that last line is the reason you would use Numpy to solve a problem like this. Otherwise, just use a list comprehension:
A = list(range(1, 6)) # same as [1, 2, 3, 4, 5]
# Same slicing, but now we have to do more work for the addition,
# by explaining the process of pairing up the elements.
Q = [x + y for x, y in zip(A[:-1], A[1:])]

Adding value to array

I want to add values from one array to another array after making some calculation, here I did it using for loop but I want efficient way doing so. Please help me.. thanx
from numpy import *
arr = array([1,2,3,4,5])
arr1 = []
for i in arr:
arr1.append(i+5)
print(arr1)
nArray = array(arr1)
print(nArray)
Output :
[6, 7, 8, 9, 10]
[ 6 7 8 9 10]
You should have just done:
nArray = arr + 5
You could use the map builtin function from Python, it takes a function and an iterable as input and returns something that you can give to the list function, so for instance:
list(map(lambda x: x + 5, arr))
But this would be for python built-in list
Since you are using numpy however, you can just add 5 to the numpy array as arr1 = arr + 5 as suggested by fountainhead

Replace multiple elements in numpy array with 1

In a given numpy array X:
X = array([1,2,3,4,5,6,7,8,9,10])
I would like to replace indices (2, 3) and (7, 8) with a single element -1 respectively, like:
X = array([1,2,-1,5,6,7,-1,10])
In other words, I replaced values at indices (2, 3) and (7,8) of the original array with a singular value.
Question is: Is there a numpy-ish way (i.e. without for loops and usage of python lists) around it? Thanks.
Note: This is NOT equivalent of replacing a single element in-place with another. Its about replacing multiple values with a "singular" value. Thanks.
A solution using numpy.delete, similar to #pault, but more efficient as it uses pure numpy indexing. However, because of this efficient indexing, it means that you cannot pass jagged arrays as indices
Setup
a = np.array([1,2,3,4,5,6,7,8,9,10])
idx = np.stack([[2, 3], [7, 8]])
a[idx] = -1
np.delete(a, idx[:, 1:])
array([ 1, 2, -1, 5, 6, 7, -1, 10])
I'm not sure if this can be done in one step, but here's a way using np.delete:
import numpy as np
from operator import itemgetter
X = np.array(range(1,11))
to_replace = [[2,3], [7,8]]
X[list(map(itemgetter(0), to_replace))] = -1
X = np.delete(X, list(map(lambda x: x[1:], to_replace)))
print(X)
#[ 1 2 -1 5 6 7 -1 10]
First we replace the first element of each pair with -1. Then we delete the remaining elements.
Try np.put:
np.put(X, [2,3,7,8], [-1,0]) # `0` can be changed to anything that's not in the array
print(X[X!=0]) # whatever You put as an number in `put`
So basically use put to do the values for the indexes, then drop the zero-values.
Or as #khan says, can do something that's out of range:
np.put(X, [2,3,7,8], [-1,np.max(X)+1])
print(X[X!=X.max()])
All Output:
[ 1 2 -1 5 6 7 -1 10]

Function that acts on all elements of numpy array?

I wonder if you can define a function to act on all elements of a 1-D numpy array simultaneously, so that you don't have to loop over the array. Similar to the way you can, for example, square all elements of an array without looping. An example of what I'm after is to replace this code:
A = np.array([ [1,4,2], [5,1,8], [2,9,5], [3,6,6] ])
B = []
for i in A:
B.append( i[0] + i[1] - i[2] )
B = array(B)
print B
Output:
>>> array([3, -2, 6, 3])
With something like:
A = np.array([ [1,4,2], [5,1,8], [2,9,5], [3,6,6] ])
def F(Z):
return Z[0] + Z[1] - Z[2]
print F(A)
So that the output is something like:
>>> array( [ [3] , [-2], [6], [3] ] )
I know the 2nd code won't produce what I'm after, but I'm just trying to give an idea of what I'm talking about. Thanks!
EDIT:
I used the function above just as a simple example. The real function I'd like to use is something like this:
from numpy import linalg as LA
def F(Z):
#Z is an array of matrices
return LA.eigh(Z)[0]
So I have an array of 3x3 matrices, and I'd like an output array of their eigenvalues. And I'm wondering if it's possible to do this in some numpythonic way, so as not to have to loop over the array.
Try:
np.apply_along_axis(F, 1, A)

Categories