Subtract a value from several arrays - python

I need to subtract a number from my numpy arrays.
Let's say, we have two arrays and I need to subtract 10 from each of its elements.
a = numpy.array([10, 11, 23, 45])
b = numpy.array([55, 23, 54, 489, 45, 12])
To do that, I enter:
a - 10
b - 10
And I get the desired output, which is:
array([ 0, 1, 13, 35])
array([ 45, 13, 44, 479, 35, 2])
But, as I have lots of such arrays, I was wondering if it is possible to get the same result, for example by entering (a,b)-10?

numpy.array([a,b]) - 10 will work.

If you enter:
numpy.array((a, b)) - 10
You get the desired result:
array([[ 0 1 13 35], [ 45 13 44 479 35 2]], dtype=object)
(a,b) - 10 doesn't work because mathematical operations only work element-by-element when operating on numpy arrays. So, the solution, as above, is to put a and b into one numpy array.

Related

Index-based addition with multiplicity in numpy

Suppose I have a numpy array
nparr = np.array([10,20,30,40,50])
The output of the operation nparr[[1,3,3,4]] += 1 on this array is:
array([10, 21, 30, 41, 51])
Even though the index '3' appears twice. Is there any operation that would let me add with multiplicity, so that the result becomes array([10, 21, 30, 42, 51])?
You can use the np.add.at method to add elements to a NumPy array with multiplicity.
import numpy as np
# Create a NumPy array
nparr = np.array([10, 20, 30, 40, 50])
# Use np.add.at to add elements to the array with multiplicity
np.add.at(nparr, [1, 3, 3, 4], [1, 1, 1, 1])
# Print the updated array
print(nparr)
In this code, the np.add.at method is used to add 1 to the elements at indices 1, 3, and 4 in the array nparr, and to add 2 to the element at index 3 in the array (since the index appears twice in the list of indices). The output of this code is:
array([10, 21, 30, 42, 51])
As you can see, the values were added to the array with multiplicity, so that the element at index 3 was incremented by 2 instead of 1.

Numpy - select multiple squares from 2d array

I have a 2d array, and a list of <start_y, height, start_x, width>.
What I need is to select squares according to the list,
So, for example if this is my 2d array:
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]]
and the list is:
[[1,3,2,5],
[2,2,0,3]]
I need the output to be:
[[12,13,14,15,16,
22,23,24,25,26,
32,33,34,35,36],
[20,21,22,
30,31,32]]
i.e. - the first square starts from index 1 in the y axis, with height of 3, and in index 2 in the x axis with width of 5 - and the same logic for the second element in the list.
I obviously tried things like arr[l[:,0]:l[:,0]+l[:,1],l[:,2]:l[:,2]+l[:,3]] where arr is the array and l is the list, but it all returned an invalid syntax error.
I guess the solution involves advanced broadcasting, but I couldn't figure it out by my own.
Any help will be appreciated!
EDIT:
I'm looking for a solution without for loop (it is currently implemented with a loop, and I'm looking to make my code more efficient).
Here's a difficulty: your squares are of different sizes. Most broadcasting or useful functions will result in one array. If your squares were the same size, we could probably figure out how to get a stacked version of them into a 3d array. But if they're different sizes, how would we stack them? Nothing wrong with a for-loop here.
Read this: https://numpy.org/doc/stable/reference/arrays.indexing.html
No "advanced broadcasting" needed.
import numpy as np
arr = np.array([
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19,],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29,],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39,],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49,],
])
coords = np.array([
[1,3,2,5],
[2,2,0,3],
])
for coord in coords:
y, h, x, w = coord
sq = arr[y:y+h, x:x+w]
print(sq)
Might be easier in your code to make a function
def get_square(arr, coord):
y, h, x, w = coord
return arr[y:y+h, x:x+w]

Deleting specific numbers from a (2,60) numpy array?

I have a numpy array that has a shape of (2,60). Some of the numbers in the first row exceed 30 and I want to filter columns for which the value of the first row is less than 30.
I tried array = array[array < 30] #but that doesn't work
An example of my array is
array = np.array([[30,40,12,12,10,2,30,40],[2,5,75,67,89,5,3,4]])
Expected output:
array = [[12 12 10 2]
[75 67 89 5]]
You are looking for this:
array[:,array[0]<30]
output:
array([[12, 12, 10, 2],
[75, 67, 89, 5]])

Cummulative addition in a loop

I am trying to cummatively add a value to the previous value and each time, store the value in an array.
This code is just part of a larger project. For simplicity i am going to define my variables as follows:
ele_ini = [12]
smb = [2, 5, 7, 8, 9, 10]
val = ele_ini
for i in range(len(smb)):
val += smb[i]
print(val)
elevation_smb.append(val)
Problem
Each time, the previous value stored in elevation_smb is replaced by the current value such that the result i obtain is:
elevation_smb = [22, 22, 22, 22, 22, 22]
The result i am expecting however is
elevation_smb = [14, 19, 26, 34, 43, 53]
NOTE:
ele_ini is a vector with n elements. I am only using 1 element just for simplicity.
Don use loops, because slow. Better is fast vectorized solution below.
I think need numpy.cumsum and add vector ele_ini for 2d numpy array:
ele_ini = [12, 10, 1, 0]
smb = [2, 5, 7, 8, 9, 10]
elevation_smb = np.cumsum(np.array(smb)) + np.array(ele_ini)[:, None]
print (elevation_smb)
[[14 19 26 34 43 53]
[12 17 24 32 41 51]
[ 3 8 15 23 32 42]
[ 2 7 14 22 31 41]]
It seems vector in your case is using pointers. That's why it is not creating new values. Try adding copy() which copies the value.
elevation_smb.append(val.copy())
Do with reduce,
In [6]: reduce(lambda c, x: c + [c[-1] + x], smb, ele_ini)
Out[6]: [12, 14, 19, 26, 34, 43, 53]

Taking an average of an array according to another array of indices

Say I have an array that looks like this:
a = np.array([0, 20, 40, 30, 60, 35, 15, 18, 2])
and I have an array of indices that I want to average between:
averaging_indices = np.array([2, 4, 7, 8])
What I want to do is to average the elements of array a according to the averaging_indices array. Just to make that clear I want to take the averages:
np.mean(a[0:2]), np.mean(a[2:4]), np.mean(a[4:7]), np.mean(a[7,8]), np.mean(a[8:])
and I want to return an array that then has the correct dimensions, in this case
result = [10, 35, 36.66, 18, 2]
Can anyone think of a neat way to do this? The only way I can imagine is by looping, which is very anti-numpy.
Here's a vectorized approach with np.bincount -
# Create "shifts array" and then IDs array for use with np.bincount later on
shifts_array = np.zeros(a.size,dtype=int)
shifts_array[averaging_indices] = 1
IDs = shifts_array.cumsum()
# Use np.bincount to get the summations for each tag and also tag counts.
# Thus, get tagged averages as final output.
out = np.bincount(IDs,a)/np.bincount(IDs)
Sample input, output -
In [60]: a
Out[60]: array([ 0, 20, 40, 30, 60, 35, 15, 18, 2])
In [61]: averaging_indices
Out[61]: array([2, 4, 7, 8])
In [62]: out
Out[62]: array([ 10. , 35. , 36.66666667, 18. , 2. ])

Categories

Resources