So I have three NumPy arrays, all with 300 elements in them. Is there any way I could create a new array with the greatest value at each index? I'm not sure where to start since I'm not comparing numbers in the same list. I know there is some kind of loop where you start from 0 to the length and you need to initialize an empty array to populate, but I'm not sure how'd you compare the values at each index. Very likely I'm overthinking.
Ex.
a = [16,24,52]
b = [22,15,136]
c = [9,2,142]
Output = [22,24,142]
Since all your arrays have the same lenghts, you can stack them vertically by using np.vstack. Then, use np.max on axis=0:
import numpy as np
a = np.array([16, 24, 52])
b = np.array([22, 15, 136])
c = np.array([9, 2, 142])
out = np.max(np.vstack((a, b, c)), axis=0)
print(out)
Output:
[ 22 24 142]
Hope that helps!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.1
NumPy: 1.18.1
----------------------------------------
You can use amax.
np.amax(np.array([a,b,c]), axis=0)
Output:
array([ 22, 24, 142])
If you want to follow your original idea involving a loop and the initialization of an array, you can use np.zeros() followed by range() and max():
import numpy as np
a = np.array([16, 24, 52])
b = np.array([22, 15, 136])
c = np.array([9, 2, 142])
# initialize array filled with zeros
Output = np.zeros(len(a), dtype=int)
# populate array
for i in range(len(a)):
Output[i] = max(a[i], b[i], c[i])
print(Output)
Output:
[ 22 24 142]
Related
So i have two arrays as shown in the example below:
import os
import numpy as np
tiA = np.array([0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2]) * 1000
tiB = np.array([0.1,0.2,0.4,0.5,0.6,0.7,0.8,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2]) * 1000
res = [idx for idx, elem in enumerate(tiB)
if elem != tiA[idx]]
print(res)
It gives me an answer of [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]. However i wanted to get position 3 and position 9 or [2,8] as an answer because 0.3 and 0.9 is missing from tiB compared to tiA. Also how can i use this answer to select a 4d array. So my array is sized arrayA=(128x128x5xtiA). However i want my new array to be sized arrayB=(128x128x5xtiB) selected from tiA. So basically arrayB will be missing [2,8] of the 4th dimension as shown in my example as compared to arrayA. My problem is most of the time there can be multiple differences (1,2,3 missing) between tiA and tiB. Thank you for all your help.
Kevin
Your code was already a good start, but you need to check if the element is not in the other list and not if the elements at the same position are equal.
import numpy as np
tiA = np.array([0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2]) * 1000
tiB = np.array([0.1,0.2,0.4,0.5,0.6,0.7,0.8,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2]) * 1000
res = [idx for idx, elem in enumerate(tiA) if elem not in tiB]
print(res)
For the second part you should be able to use np.delete. You just need to define the indices (res) and the correct axis (should be 3 in your case then).
arrayB = np.delete(arrayA, res, 3))
I have the following numpy array
u = np.array([a1,b1,a2,b2...,an,bn])
where I would like to subtract the a and b elements from each other and end up with a numpy array:
u_result = np.array([(a2-a1),(b2-b1),(a3-a2),(b3-b2),....,(an-a_(n-1)),(an-a_(n-1))])
How can I do this without too much array splitting and for loops? I'm using this in a larger loop so ideally, I would like to do this efficiently (and learn something new)
(I hope the indexing of the resulting array is clear)
Or simply, perform a substraction :
u = np.array([3, 2, 5, 3, 7, 8, 12, 28])
u[2:] - u[:-2]
Output:
array([ 2, 1, 2, 5, 5, 20])
you can use ravel torearrange as your original vector.
Short answer:
u_r = np.ravel([np.diff(u[::2]),
np.diff(u[1::2])], 'F')
Here a long and moore detailed explanation:
separate a from b in u this can be achieved indexing
differentiate a and b you can use np.diff for easiness of code.
ravel again the differentiated values.
#------- Create u---------------
import numpy as np
a_aux = np.array([50,49,47,43,39,34,28])
b_aux = np.array([1,2,3,4,5,6,7])
u = np.ravel([a_aux,b_aux],'F')
print(u)
#-------------------------------
#1)
# get a as elements with index 0, 2, 4 ....
a = u[::2]
b = u[1::2] #get b as 1,3,5,....
#2)
#differentiate
ad = np.diff(a)
bd = np.diff(b)
#3)
#ravel putting one of everyone
u_result = np.ravel([ad,bd],'F')
print(u_result)
You can try in this way. Firstly, split all a and b elements using array[::2], array[1::2]. Finally, subtract from b to a (np.array(array[1::2] - array[::2])).
import numpy as np
array = np.array([7,8,9,6,5,2])
u_result = np.array(array[1::2] - array[::2] )
print(u_result)
Looks like you need to use np.roll:
shift = 2
u = np.array([1, 11, 2, 12, 3, 13, 4, 14])
shifted_u = np.roll(u, -shift)
(shifted_u - u)[:-shift]
Returns:
array([1, 1, 1, 1, 1, 1])
I have a vector of the following form:
import numpy as np
vec = np.array([2, 2, 2, 51, 51, 52, 52, 14, 14, 14, 51, 51, 52, 52])
Is there a numpy-thonic way to find the index of the first occurrence of a value that is not (for instance) 51 or 52? In other words, a function that would return the following indexes: [0, 7], where 0 is the index of the first apparition of 2, and 7 is the index of the first apparition of 14.
np.unique returns the first index of each number if you specify return_index=True. You can filter the result pretty easily using, e.g., np.isin:
u, i = np.unique(vec, return_index=True)
result = i[np.isin(u, [51, 52], invert=True)]
The advantage of doing it this way is that u is a significantly reduced search space compared to the original data. Using invert=True also speeds things up a little compared to explicitly negating the resulting mask.
A version of np.isin that relies on the fact that the data is already sorted could be made using np.searchsorted like this:
def isin_sorted(a, i, invert=False):
ind = np.searchsorted(a, i)
ind = ind[a[ind.clip(max=a.size)] == i]
if invert:
mask = np.ones(a.size, dtype=bool)
mask[ind] = False
else:
mask = np.zeros(a.size, dtype=bool)
mask[ind] = True
return mask
You could use this version in place of np.isin, after calling np.unique, which always returns a sorted array. For sufficiently large vec and exclusion lists, it will be more efficient:
result = i[isin_sorted(u, [51, 52], invert=True)]
import numpy as np
vec = np.array([2, 2, 2, 51, 51, 52, 52, 14, 14, 14, 51, 51, 52, 52])
first_occurrence = []
for x in np.unique(vec):
if x not in [51,52]:
first_occurrence.append(np.argmax(x==vec))
argmax finds the index of the first occurrence of the maximum (i.e. True) in the boolean array x==vec. As x is from vec it is guaranteed that there is minimum one True value.
Performance depends on the size of vec and on how many values to find. This simple loop method (blue) outperforms the accepted answer (green and orange) for larger arrays, especially for small numbers of values to find like in the example (for the given toy example it's in fact 1.7 times faster) (source).
It turns out the using unique with index=True is relatively slow, another factor for larger arrays is the memory allocation for the mask.
The objective of task required to produce an array output such that output[i] is equal to the sum of all the elements of nums except nums[i].
Eg: given [6,7,8,9], return [24,23,22,21].
Input = [6,7,8,9]
The calculation behind is
0+7+8+9 = 24
6+0+8+9 = 23
6+7+0+9 = 22
6+7+8+0 = 21
Output = [ 24, 24, 22, 21 ]
You can use list comprehension:
In [1]: a = [6,7,8,9]
In [2]: s = sum(a)
In [3]: [s - i for i in a]
Out[3]: [24, 23, 22, 21]
Use numpy broadcasting + vectorised operations for this:
import numpy as np
x = np.array([6,7,8,9])
y = np.sum(x) - x
# array([24, 23, 22, 21])
You can use a for loop and python's inbuilt sum function
a = [6,7,8,9] #your input array
b = [] # initialise an empty list
for index in range(len(a)): #iterate through the list's length
b.append( sum( a[0:index] + a[index+1:] ) ) #add to two parts before and
# after the index
print(b)
I have an array (msaarr) of 1700 values, ranging from approximately 0 to 150. I know that 894 of these values should be less than 2, and I wish to create a new array containing only these values.
So far, I have attempted this code:
Combined = np.zeros(shape=(894,8))
for i in range(len(Spitzer)): #len(Spitzer) = 1700
index = np.where(msaarr <= 2)
Combined[:,0] = msaarr[index]
The reason there are eight columns is because I have more data associated with each value in msaarr that I also want to display. msaarr was created using several lines of code, which is why I haven't mentioned them here, but it is an array with shape (1700,1) with type float64.
The problem I'm having is that if I print msaarr[index], then I get an array of shape (893,), but when I attempt to assign this as my zeroth column, I get the error
ValueError: could not broadcast input array from shape (1699) into shape (894)
I also attempted
Combined[:,0] = np.extract(msaarr <= 2, msaarr)
Which gave the same error.
I thought at first this might just be some confusion with Python's zero-indexing, so I tried changing the shape to 893, and also tried to assign to a different column Combined[:,1], but I have the same error every time.
Alternatively, when I try:
Combined[:,1][i] = msaarr[index][i]
I get the error:
IndexError: index 894 is out of bounds for axis 0 with size 894
What am I doing wrong?
EDIT:
A friend pointed out that I might not be calling index correctly because it is a tuple, and so his suggestion was this:
index = np.where(msaarr < 2)
Combined[:,0] = msaarr[index[0][:]]
But I am still getting this error:
ValueError: could not broadcast input array from shape (893,1) into shape (893)
How can my shape be (893) and not (893, 1)?
Also, I did check, and len(index[0][:]) = 893, and len(msaarr[index[0][:]]) = 893.
The full code as of last attempts is:
import numpy as np
from astropy.io import ascii
from astropy.io import fits
targets = fits.getdata('/Users/vcolt/Dropbox/ATLAS source matches/OzDES.fits')
Spitzer = ascii.read(r'/Users/vcolt/Desktop/Catalogue/cdfs_spitzer.csv', header_start=0, data_start=1)
## Find minimum separations, indexed.
RADiffArr = np.zeros(shape=(len(Spitzer),1))
DecDiffArr = np.zeros(shape=(len(Spitzer),1))
msaarr = np.zeros(shape=(len(Spitzer),1))
Combined= np.zeros(shape=(893,8))
for i in range(len(Spitzer)):
x = Spitzer["RA_IR"][i]
y = Spitzer["DEC_IR"][i]
sep = abs(np.sqrt(((x - targets["RA"])*np.cos(np.array(y)))**2 + (y - targets["DEC"])**2))
minsep = np.nanmin(sep)
minseparc = minsep*3600
msaarr[i] = minseparc
min_positions = [j for j, p in enumerate(sep) if p == minsep]
x2 = targets["RA"][min_positions][0]
RADiff = x*3600 - x2*3600
RADiffArr[i] = RADiff
y2 = targets["DEC"][min_positions][0]
DecDiff = y*3600 - y2*3600
DecDiffArr[i] = DecDiff
index = np.where(msaarr < 2)
print msaarr[index].shape
Combined[:,0] = msaarr[index[0][:]]
I get the same error whether index = np.where(msaarr < 2) is in or out of the loop.
Take a look at using numpy.take in combination with numpy.where.
inds = np.where(msaarr <= 2)
new_msaarr = np.take(msaarr, inds)
If it is a multi-dimensional array, you can also add the axis keyword to take slices along that axis.
I think loop is not at the right place. np.where() will return an array of index of elements which matches the condition you have specified.
This should suffice
Index = np.where(msaarr <= 2)
Since index is an array. You need to loop over this index and fill the values in combined[:0]
Also I want to point out one thing. You have said that there will be 894 values less than 2 but in the code you are using less than and equal to 2.
np.where(condition) will return a tuple of arrays containing the indexes of elements that verify your condition.
To get an array of the elements verifying your condition use:
new_array = msaarr[msaarr <= 2]
>>> x = np.random.randint(0, 10, (4, 4))
>>> x
array([[1, 6, 8, 4],
[0, 6, 6, 5],
[9, 6, 4, 4],
[9, 6, 8, 6]])
>>> x[x>2]
array([6, 8, 4, 6, 6, 5, 9, 6, 4, 4, 9, 6, 8, 6])