Index-based addition with multiplicity in numpy - python

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.

Related

How to reorder a numpy array by giving each element a new index?

I want to reorder a numpy array, such that each element is given a new index.
# I want my_array's elements to use new_indicies's indexes.
my_array = np.array([23, 54, 67, 98, 31])
new_indicies = [2, 4, 1, 0, 1]
# Some magic using new_indicies at my_array
# Note that I earlier gave 67 and 31 the index 1 and since 31 is last, that is the one i'm keeping.
>>> [98, 31, 23, 0, 54]
What would be an efficient approach to this problem?
To reorder the elements in a NumPy array according to a set of new indices, you can use the put() method.
# Create an empty array of zeros with the same size as my_array
reordered_array = np.zeros_like(my_array)
# Move the elements in my_array to the indices specified in new_indices
reordered_array.put(new_indices, my_array)
print(reordered_array) # [98, 31, 23, 0, 54]

Minimum distance for each value in array respect to other

I have two numpy arrays of integers A and B. The values in array A and B correspond to time-points at which events A and B occurred. I would like to transform A to contain the time since the most recent event b occurred.
I know I need to subtract each element of A by its nearest smaller the element of B but am unsure of how to do so. Any help would be greatly appreciated.
>>> import numpy as np
>>> A = np.array([11, 12, 13, 17, 20, 22, 33, 34])
>>> B = np.array([5, 10, 15, 20, 25, 30])
Desired Result:
cond_a = relative_timestamp(to_transform=A, reference=B)
cond_a
>>> array([1, 2, 3, 2, 0, 2, 3, 4])
You can use np.searchsorted to find the indices where the elements of A should be inserted in B to maintain order. In other words, you are finding the closest elemet in B for each element in A:
idx = np.searchsorted(B, A, side='right')
result = A-B[idx-1] # substract one for proper index
According to the docs searchsorted uses binary search, so it will scale fine for large inputs.
Here's an approach consisting on computing the pairwise differences. Note that it has a O(n**2) complexity so it might for larger arrays #brenlla's answer will perform much better.
The idea here is to use np.subtract.outer and then find the minimum difference along axis 1 over a masked array, where only values in B smaller than a are considered:
dif = np.abs(np.subtract.outer(A,B))
np.ma.array(dif, mask = A[:,None] < B).min(1).data
# array([1, 2, 3, 2, 0, 2, 3, 4])
As I am not sure, if it is really faster to calculate all pairwise differences, instead of a python loop over each array entry (worst case O(Len(A)+len(B)), the solution with a loop:
A = np.array([11, 12, 13, 17, 20, 22, 33, 34])
B = np.array([5, 10, 15, 20, 25, 30])
def calculate_next_distance(to_transform, reference):
max_reference = len(reference) - 1
current_reference = 0
transformed_values = np.zeros_like(to_transform)
for i, value in enumerate(to_transform):
while current_reference < max_reference and reference[current_reference+1] <= value:
current_reference += 1
transformed_values[i] = value - reference[current_reference]
return transformed_values
calculate_next_distance(A,B)
# array([1, 2, 3, 2, 0, 2, 3, 4])

getting multiple array after performing subtraction operation within array elements

import numpy as np
m = []
k = []
a = np.array([[1,2,3,4,5,6],[50,51,52,40,20,30],[60,71,82,90,45,35]])
for i in range(len(a)):
m.append(a[i, -1:])
for j in range(len(a[i])-1):
n = abs(m[i] - a[i,j])
k.append(n)
k.append(m[i])
print(k)
Expected Output in k:
[5,4,3,2,1,6],[20,21,22,10,10,30],[25,36,47,55,10,35]
which is also a numpy array.
But the output that I am getting is
[array([5]), array([4]), array([3]), array([2]), array([1]), array([6]), array([20]), array([21]), array([22]), array([10]), array([10]), array([30]), array([25]), array([36]), array([47]), array([55]), array([10]), array([35])]
How can I solve this situation?
You want to subtract the last column of each sub array from themselves. Why don't you use a vectorized approach? You can do all the subtractions at once by subtracting the last column from the rest of the items and then column_stack together with unchanged version of the last column. Also note that you need to change the dimension of the last column inorder to be subtractable from the 2D array. For that sake we can use broadcasting.
In [71]: np.column_stack((abs(a[:, :-1] - a[:, None, -1]), a[:,-1]))
Out[71]:
array([[ 5, 4, 3, 2, 1, 6],
[20, 21, 22, 10, 10, 30],
[25, 36, 47, 55, 10, 35]])

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. ])

Python, find the index of 1D array that is filled with arrays of tuple

I have a 1D array. each element holds a unique value IE [2013 12 16 1 10] so array[0,0] would be [2013] array[0,1] would be [12]. array[0,0:2] would be [2013 12].
When I try array.index(array[0,0:5]). It creates error and says that list indicies must be integers, not tuple. find the index of a specific element if the element is [2013 12 16 1 10] a tuple...?
If you have a 1D array, then array[0,0] is invalid. Try this link:
http://www.thegeekstuff.com/2013/08/python-array/
Since this is a 1D array, you do:
my_array = [2013, 12, 16, 1, 10]
position for 2013 would be:
my_array[0]
I you want to do: my_array[0,0], then you need: `my_array = [[2013, 12, 16, 1, 10]]
Also check the link posted by: Musfiqur rahman
If you have a 1 dimensional array, that is simply an array of values like you mentioned where the array could equal [2013, 12, 16, 1, 10]. You access individual items in the array by using array[index]. However, there are actually 3 parameters used for getting array values:
array[start:end:step]
array[0, 1] is invalid, as the syntax is using colons not commas. 0,1 evaluates to a tuple of 2 values, (0, 1). If you want to get the value of 12, you need to say array[1]
Because you are talking about a 1D array then you must do the following:
myArray = [44, 62, 2013, 2, 1, 10]
#the position for 62 would be:
myArray[1]
Then if you want to get a few values from your array you should you ":" not ",". For example:
myArray = [44, 62, 2013, 2, 1, 10]
#the position for 62, 2013, 2, 1 would be:
myArray[1:4]

Categories

Resources