Suppose I have a Numpy array, such as
rand = np.random.randn(6, 6)
I need the central four values in the array, since it has axes of even length. If it had been odd, such as 5 by 5, then there would only be one central value. What is the simplest/fastest/easiest way of retrieving these four entries? I can obtain them very crudely with indices, but I'm looking for a faster way than calling a bunch of functions and performing a bunch of calculations.
For example, consider the following:
array([[ 0.25659355, -0.75456113, 0.39467396, 0.50805361],
[-0.77218172, 1.00016061, -0.70389486, 1.67632146],
[-0.41106158, -0.63757421, 1.70390504, -0.79073362],
[-0.2016959 , 0.55316318, -1.55280823, 0.45740193]])
I want the following:
array([[1.00016061, -0.70389486],
[-0.63757421, 1.70390504]])
But not just for a 4 by 4 array - if it is even by even, I want the central four elements, as above.
Is something like this too complicated?
def get_middle(arr):
n = arr.shape[0] / 2.0
n_int = int(n)
if n % 2 == 1:
return arr[[n_int], [n_int]]
else:
return arr[n_int:n_int + 2, n_int:n_int + 2]
You can do this with a single slicing operation:
rand = np.random.randn(n,n)
# assuming n is even
center = rand[n/2-1:n/2+1, n/2-1:n/2+1]
I'm abusing order of operations by leaving out the parens, just to make it a little less messy.
Given array a:
import numpy as np
a = np.array([[ 0.25659355, -0.75456113, 0.39467396, 0.50805361],
[-0.77218172, 1.00016061, -0.70389486, 1.67632146],
[-0.41106158, -0.63757421, 1.70390504, -0.79073362],
[-0.2016959 , 0.55316318, -1.55280823, 0.45740193]])
The easiest way to get the central 4 values is:
ax, ay = a.shape
a[int(ax/2)-1:int(ax/2)+1, int(ay/2)-1:int(ay/2)+1]
This works if you have even numbers for the dimensions of the array. In case of odd numbers, there won't be a central 4 values.
Could you just use indexing? Like:
A = np.array([[ 0.25659355, -0.75456113, 0.39467396, 0.50805361],
[-0.77218172, 1.00016061, -0.70389486, 1.67632146],
[-0.41106158, -0.63757421, 1.70390504, -0.79073362],
[-0.2016959 , 0.55316318, -1.55280823, 0.45740193]])
])
A[1:3,1:3]
Or if matrix A had odd dimensions, say 5x5 then:
A[2,2]
Related
I have two numpy arrays with 0s and 1s in them. How can I find the indexes with 1 in the first array and 0 in the second?
I tried np.logical_and
But got error message (builtin_function_or_method' object is not subscriptable)
Use np.where(arr1==1) and np.where(arr2==0)
import numpy as np
array1 = np.array([0,0,0,1,1,0,1])
array2 = np.array([0,1,0,0,1,0,1])
ones = np.where(array1 == 1)
zeroes = np.where(array2 == 0)
print("array 1 has 1 at",ones)
print("array 2 has 0 at",zeroes)
returns:
array 1 has 1 at (array([3, 4, 6]),)
array 2 has 0 at (array([0, 2, 3, 5]),)
I'm not sure if theres some built-in numpy function that will do this for you, since it's a fairly specific problem. EDIT: there is, see bottom
Nonetheless, if one were to exist, it would have to be a linear time algorithm if you're passing in a bare numpy array, so writing your own isn't difficult.
If I have any numpy array (or python array) myarray, and I want a collection of indices where some object myobject appears, we can do this in one line using a list comprehension:
indices = [i for i in range(len(myarray)) if myarray[i] == myobject]
So what's going on here?
A list comprehension works in the following format:
[<output> for <input> in <iterable> if <condition>]
In our case, <input> and <output> are the indices of myarray, and the <condition> block checks if the value at the current index is equal to that of our desired value.
Edit: as White_Sirilo helpfully pointed out, numpy.where does the same thing, I stand corrected
Let's say your arrays are called j and k. The following code returns all indices where j[index] = 1 and k[index] = 0 if both arrays are 1-dimensional. It also works if j and k are different sizes.
idx_1 = np.where(j == 1)[0]
idx_2 = np.where(k == 0)[0]
final_indices = np.intersect1d(idx_1, idx_2, return_indices=False)
If your array is 2-dimensional, you can use the above code in a function and then go row-by-row. There are almost definitely better ways to do this, but this works in a pinch.
tow numpy array given in problem.
array1 and array2
just use
one_index=np.where(array1==1)
and
zero_index=np.where(array2==0)
I want the first array to display it's values only when common indices values of both the arrays are greater than zero else make it zero. I'm not really sure how to frame the question. Hopefully the expected output provides better insight.
I tried playing around with np.where, but I can't seem to make it work when 2 arrays are provided.
a = np.array([0,2,1,0,4])
b = np.array([1,1,3,4,0])
# Expected Output
a = ([0,2,1,0,0])
The zip function, which takes elements of two arrays side by side, is useful here. You don't necessarily need an np/numpy function.
import numpy as np
a = np.array([0,2,1,0,4])
b = np.array([1,1,3,4,0])
c = np.array([x if x * y > 0 else 0 for x,y in zip(a, b)])
print(c)
So I feel like I might have coded myself into a corner -- but here I am.
I have created a dictionary of arrays (well specifically ascii Columns) because I needed to create five arrays performing the same calculation on an array with five different parameters (The calculation involved multiplying arrays and one of five arbitrary constants).
I now want to create an array where each element corresponds to the sum of the equivalent element from all five arrays. I'd rather not use the ugly for loop that I've created (it's also hard to check if i'm getting the right answer with the loop).
Here is a modified snippet for testing!
import numpy as np
from astropy.table import Column
from pylab import *
# The five paramaters for the Columns
n1 = [14.18,19.09,33.01,59.73,107.19,172.72] #uJy/beam
n2 = [14.99,19.04,32.90,59.99,106.61,184.06] #uJy/beam
n1 = np.array([x*1e-32 for x in n1]) #W/Hz
n2 = np.array([x*1e-32 for x in n2]) #W/Hz
# an example of the arrays being mathed upon
luminosity=np.array([2.393e+24,1.685e+24,2.264e+23,5.466e+22,3.857e+23,4.721e+23,1.818e+23,3.237e+23])
redshift = np.array([1.58,1.825,0.624,0.369,1.247,0.906,0.422,0.66])
field = np.array([True,True,False,True,False,True,False,False])
DMs = {}
for i in range(len(n1)):
DMs['C{0}'.format(i)]=0
for SC,SE,level in zip(n1,n2,DMs):
DMmax = Column([1 for x in redshift], name='DMmax')
DMmax[field]=(((1+redshift[field])**(-0.25))*(luminosity[field]/(4*pi*5*SE))**0.5)*3.24078e-23
DMmax[~field]=(((1+redshift[~field])**(-0.25))*(luminosity[~field]/(4*pi*5*SC))**0.5)*3.24078e-23
DMs[level] = DMmax
Thanks all!
Numpy was built for this! (provided all arrays are of the same shape)
Just add them, and numpy will move element-wise through the arrays. This also has the benefit of being orders of magnitude faster than using a for-loop in the Python layer.
Example:
>>> n1 = np.array([1,2,3])
>>> n2 = np.array([1,2,3])
>>> total = n1 + n2
>>> total
array([2,4,6])
>>> mask = np.array([True, False, True])
>>> n1[mask] ** n2[mask]
array([ 1, 27])
Edit additional input
You might be able to do something like this:
SE_array = (((1+redshift[field]) ** (-0.25)) * (luminosity[field]/(4*pi*5*n1[field])) ** 0.5) * 3.24078e-23
SC_array = (((1+redshift[field]) ** (-0.25)) * (luminosity[field]/(4*pi*5*n2[field])) ** 0.5) * 3.24078e-23
and make the associations by stacking the new arrays:
DM = np.dstack((SE_array, SC_array))
reshaper = DM.shape[1:] # take from shape (1, 6, 2) to (6,2), where 6 is the length of the arrays
DM = DM.reshape(reshaper)
This will give you a 2d array like:
array([[SE_1, SC_1],
[SE_2, SC_2]])
Hope this is helpful
If you can't just add the numpy arrays you can extract the creation of the composite array into a function.
def get_element(i):
global n1, n2, luminosity, redshift, field
return n1[i] + n2[i] + luminosity[i] + redshift[i] + field[i]
L = len(n1)
composite = [get_element(i) for i in range(L)]
The answer was staring at me in the face, but thanks to #willnx, #cricket_007, and #andrew-lavq. Your suggestions made me realise how simple the solution is.
Just add them, and numpy will move element-wise through the arrays. -- willnx
You need a loop to sum all values of a collection -- cricket_007
so it really is as simple as
sum(x for x in DMs.values())
I'm not sure if this is the fastest solution, but I think it's the simplest.
I have defined operations on 3xN NumPy arrays, and I want to loop over each column of the array.
I tried:
for i in range(nparray.shape[1]):
However, if nparray.ndim == 1, this fails.
Is there a clean way to ascertain the number of columns of a NumPy array, for example, to get 1 if it is a 1D array (like MATLAB's size operation does)?
Otherwise, I have implemented:
if nparray.ndim == 1:
num_points = 1
else:
num_points = nparray.shape[1]
for i in range(num_points):
If you're just looking for something less verbose, you could do this:
num_points = np.atleast_2d(nparray).shape[1]
That will, of course, make a new temporary array just to take its shape, which is a little silly… but it'll be pretty cheap, because it's just a view of the same memory.
However, I think your explicit code is more readable, except that I might do it with a try:
try:
num_points = nparray.shape[1]
except IndexError:
num_points = 1
If you're doing this repeatedly, whatever you do, you should wrap it in a function. For example:
def num_points(arr, axis):
try:
return arr.shape[axis]
except IndexError:
return 1
Then all you have to write is:
for i in range(num_points(nparray, 1)):
And of course it means you can change things everywhere by just editing one place, e.g.,:
def num_points(arr, axis):
return nparray[:,...,np.newaxis].shape[1]
If you want to keep the one-liner, how about using conditional expressions:
for i in range(nparray.shape[1] if nparray.ndim > 1 else 1):
pass
By default, to iterate a np.array means to iterate over the rows. If you have to iterate over columns, just iterate through the transposed array:
>>> a2=array(range(12)).reshape((3,4))
>>> for col in a2.T:
print col
[0 4 8]
[1 5 9]
[ 2 6 10]
[ 3 7 11]
What's the intended behavior of an array array([1,2,3]), it is treated as having one column or having 3 cols? It is confusing that you mentioned that the arrays are all 3XN arrays, which means this should be the intended behavior, as it should be treated as having just 1 column:
>>> a1=array(range(3))
>>> for col in a1.reshape((3,-1)).T:
print col
[0 1 2]
So, a general solution: for col in your_array.reshape((3,-1)).T: #do something
I think the easiest way is to use the len function:
for i in range(len(nparray)):
...
Why? Because if the number of nparray is a like a one dimensional vector, len will return the number of elements. In your case, the number of columns.
nparray = numpy.ones(10)
print(len(nparray))
Out: 10
If nparray is like a matrix, the number of columns will be returned.
nparray = numpy.ones((10, 5))
print(len(nparray))
Out: 10
If you have a list of numpy arrays with different sizes, just use len inside a loop based on your list.
Given the number of rows (or columns) , n, of a square matrix, I am trying to get the index pairs of the lower triangular matrix in a 1 dimensional list. So far I thought of the following solution:
def getLowerTriangularIndices(n):
inds=[];
for i in range(1,n):
for j in range(i):
inds.append((i,j))
return inds;
Considering the two for loops, it would be far better to have a more efficient way of calculating this maybe using numpy. Does anyone have a suggestion?
Numpy has a method for that...
import numpy as np
# create your matrix. If it's not yet a numpy array, make it one
ar = np.array(matrix)
indices = np.tril_indices_from(ar)
This returns a tuple of two arrays. If you want to have them as lists, you could do
indices = [list(x) for x in np.tril_indices_from(ar)]
You actually do not need to have an array to get the indices, there is also np.tril_indices, which takes the shape as arguments.
So your function would read:
def getLowerTriangularIndices(n):
return [list(x) for x in np.tril_indices(n)]
or if you want a list of tuples instead:
def getLowerTriangularIndices(n):
return zip(*np.tril_indices(n)]