Slicing a 2d array in python via another array in one line - python

Apologies is the title is not correct. I didn't know how to describe exactly what I am looking for.
So coming from Matlab I want to be able to do the following in Python in one line if possible
Say I have an index array:
index_array= np.array([0,1,1,0,0,0,1])
and a data array:
data_array = np.zeros([len(index_array),2])
I want to place a value (e.g. 100) where index_array=0 to the data_array[:,0] and where index_array=1 to data_array[:,1]
I matlab you could do it with one line. Something like
data_array(index_array)=100
The best I could figure out in python is this
data_array [index_array==0,0]=100
data_array [index_array==1,1]=100
Is it possible to do it more efficiently (w.r.t. lines of code). Also it would be nice to scale for additional dimensions in data_array (beyond 2d)

If I understand your question correctly, please try this:
import numpy as np
index_array= np.array([0,1,1,0,0,0,1],dtype=bool)
data_array = np.zeros([len(index_array),2])
data_array[index_array,:]=100
print(data_array)
Here, index_array is instantiated as boolean. Or it can convert index_array to boolean using == (index_array==0).
Use data_array[index_array,...]=100 if there are additional dimensions.
------ CORRECTED VERSION ------
Hope I now understand your question. So try this:
import numpy as np
index_array= np.array([0,1,1,0,2,0,1,2])
data_array = np.zeros([len(index_array),3])
data_array[np.arange(len(index_array)), index_array] = 100
print(data_array)

Related

numpy : slice an array while looping around borders of array (topology of a donut)

I'm trying to slice a numpy array by potentially overlapping the borders of the array. I expected to have a topological doughnut in my hands, but this doesn't lead to what I expected to be.
as an example is worth a thousand words :
import numpy as np
# a 10x10 array with c
arr =np.array([[ c + 10 * r for c in range(10)] for r in range(10) ])
print(t[1:3,8:1])
gives
[]
even though I would have expected :
[[ 81,82],
[ 91,92],
[ 1, 2]]
I thought that python supported negative position but it fails too when using :
print(t[1:3,-2:1])
[]
Am I missing something?
as hpaulj mentionned it is not possible.
However, it is possible to use numpy.append or and create a new array storing the custom-slice.
Unfortunately, this would make changing data in the original array by editing data in the slice impossible.
This last limitation makes it impractical and useless for my case, but if you stumble on this question and you don't need the result to be reference, feel free to leave a like.

How to remove the double [[ for a 1D matrix in python?

I am working on a Deep Learning project (in Python), and I had a problem with my code. I get an output like this:
[[-0.00111287 -0.97692661 -0.9939433 -0.99474857]]
and I want to change that to this:
[-0.00111287 -0.97692661 -0.9939433 -0.99474857]
Can anyone help me with a simple function. I could not find any function that did the job.
Thanks in advance!
I assume that you have a numpy.ndarray? You can flatten any array into 1D by doing array.ravel(). Additionally, you can reshape an array into any desired shape (compatible with the number of elements in the array) using array.reshape. array.reshape(-1) is the same as array.ravel(). See here for more on reshaping arrays. Finally, you could also get array_1d = array_2d[0], but I don't find this as clear in code because it seems to the reader like you are just selecting the first row of a 2D array. Doing array_1d = array_2d.ravel() makes it clear that you are keeping all elements, just flattening the array.
Try this:
import numpy as np
my_matrix = [[-0.00111287, -0.97692661, -0.9939433, -0.99474857]]
result = list(np.array(my_matrix).reshape(-1))
print(result)
# [-0.00111287, -0.97692661, -0.9939433, -0.99474857]
If you're not working with a numpy array, itertools provides a function called chain() that can be used to flatten a list:
from itertools import chain
array = list(chain(*matrix))

Storing arrays in Python for loop

Let's say I have a function (called numpyarrayfunction) that outputs an array every time I run it. I would like to run the function multiple times and store the resulting arrays. Obviously, the current method that I am using to do this -
numpyarray = np.zeros((5))
for i in range(5):
numpyarray[i] = numpyarrayfunction
generates an error message since I am trying to store an array within an array.
Eventually, what I would like to do is to take the average of the numbers that are in the arrays, and then take the average of these averages. But for the moment, it would be useful to just know how to store the arrays!
Thank you for your help!
As comments and other answers have already laid out, a good way to do this is to store the arrays being returned by numpyarrayfunction in a normal Python list.
If you want everything to be in a single numpy array (for, say, memory efficiency or computation speed), and the arrays returned by numpyarrayfunction are of a fixed length n, you could make numpyarray multidimensional:
numpyarray = np.empty((5, n))
for i in range(5):
numpyarray[i, :] = numpyarrayfunction
Then you could do np.average(numpyarray, axis = 1) to average over the second axis, which would give you back a one-dimensional array with the average of each array you got from numpyarrayfunction. np.average(numpyarray) would be the average over all the elements, or np.average(np.average(numpyarray, axis = 1)) if you really want the average value of the averages.
More on numpy array indexing.
I initially misread what was going on inside the for loop there. The reason you're getting an error is because numpy arrays will only store numeric types by default, and numpyarrayfunction is returning a non-numeric value (from the name, probably another numpy array). If that function already returns a full numpy array, then you can do something more like this:
arrays = []
for i in range(5):
arrays.append(numpyarrayfunction(args))
Then, you can take the average like so:
avgarray = np.zeros((len(arrays[0])))
for array in arrays:
avgarray += array
avgarray = avgarray/len(arrays)

2D python list of numpy arrays to 2D numpy array

Which is the most performant way
to convert something like that
problem = [ [np.array([1,2,3]), np.array([4,5])],
[np.array([6,7,8]), np.array([9,10])]]
into
desired = np.array([[1,2,3,4,5],
[6,7,8,9,10]])
Unfortunately, the final number of columns and rows (and length of subarrays) is not known in advance, as the subarrays are read from a binary file, record by record.
How about this:
problem = [[np.array([1,2,3]), np.array([4,5])],
[np.array([6,7,8]), np.array([9,10])]]
print np.array([np.concatenate(x) for x in problem])
I think this:
print np.array([np.hstack(i) for i in problem])
Using your example, this runs in 0.00022s, wherease concatenate takes 0.00038s
You can also use apply_along_axis although this runs in 0.00024s:
print np.apply_along_axis(np.hstack, 1, problem)

Manipulating copied numpy array without changing the original

I am trying to manipulate a numpy array that contains data stored in an other array. So far, when I change a value in my array, both of the arrays get values changed:
import numpy as np
from astropy.io import fits
image = fits.getdata("randomImage.fits")
fft = np.fft.fft2(image)
fftMod = np.copy(fft)
fftMod = fftMod*2
if fftMod.all()== fft.all():
print "shit same same same "
-- > shit same same same
Why is?
You misunderstood the usage of the .all() method.
It yields True if all elements of an array are not 0. This seems to be the case in both your arrays or in neither of them.
Since one is the double of the other, they definetly give the same result to the .all() method (both True or both False)
edit as requested in the comments:
To compare the content of the both arrays use element wise comparison first and check that all elements are True with .all:
(fftMod == fft).all()
Or maybe better for floats including a certain tolerance:
np.allclose(fftMod, fft)

Categories

Resources