python - Populating Array with an indexed array - python

I have a numpy array called "PRECIP" with shape (2,3,3) which corresponds to (time, lat, lon)
array([[[ 0.05368402, 0.43843025, 0.09521903],
[ 0.22627141, 0.12920409, 0.17039465],
[ 0.48148674, 0.59170703, 0.41321763]],
[[ 0.63621704, 0.11119242, 0.25992372],
[ 0.67846732, 0.3710733 , 0.25641174],
[ 0.1992151 , 0.86837441, 0.80136514]]])
I have another numpy array called "idx" which is a list of indices, with the shape (3, 4):
array([[0,0,1,1], # time
[0,2,0,2], # x coordinate
[0,2,0,2]]) # y coordinate
So far I have been able to index the "PRECIP" variable with the "idx" variable so that I get an array with the shape (4,), ie.
>>>accum = PRECIP[idx[0,:],idx[1,:],idx[2,:]]
array([ 0.05368402, 0.41321763, 0.63621704, 0.80136514])
BUT, what I need is an array of zeros "ACCUM" with the shape (3,3), populated with the sum of "PRECIP" for each pair of coordinates in "IDX". All other gridpoints not listed in "IDX" would be 0.
Basically I want an array "accum" that looks like this
>>>accum
array([[[ 0.68990106, 0. , 0. ], # 0.68990106 = 0.05368402 + 0.63621704
[ 0. , 0. , 0. ],
[ 0. , 0. , 1.21458277], # 1.21458277 = 0.41321763 + 0.80136514
I'd appreciate any help! Thanks :)

If I understand correctly what you need is:
array = [0.5] * 249
It will return an array of length 249 populated with 0.5 in each index. After that you can slice it if its necesary to retrieve the amount of elements you like.
If that is not what you want, you can use dictionaries and add a key that is the tuple that you want this way.
dict = {(40, 249): array}
I hope it helps.

Convert any NaNs in the Lat and Lon columns of PRECIP to zero, then sum them and reshape the result.
np.nan_to_num(PRECIP[idx[1,:], idx[2,:]]).sum(axis=1).reshape(PRECIP.shape[1], PRECIP.shape[2])

Related

How can i scale between [0,1] a random matrix

I have to scale between [0,1] a matrix. So, for each element from matrix i have to do this formula:
(Element - min_cols) / (max_cols - min_cols)
min_cols -> array with every minimum of each column from the matrix. max_cols -> same but with max
My problem is, i want to calculate result with this:
result = (Element- min_cols) / (max_cols - min_cols)
Or, from each element from the matrix i have to do difference between that element and the minimum from element's column, and do the difference between (maximum element's column and the minimum).*
but when i have for example the value from min_cols negative and the value from max_cols also negative, it results the sum between both.
I want to specify that the matrix is: _mat = np.random.randn(1000, 1000) * 50
Use numpy
Example
import numpy as np
x = 50*np.random.rand(6,4)
array([[26.7041017 , 46.88118463, 41.24541748, 31.17881807],
[47.57036124, 16.49040094, 6.62454156, 37.15976348],
[46.7157895 , 8.53357717, 39.01399714, 5.14287858],
[24.36012016, 5.67603151, 40.7697121 , 13.09877845],
[21.69045322, 12.61989002, 8.74692768, 46.23368735],
[ 3.9058066 , 35.50845507, 4.66785679, 2.34177134]])
Apply your formula
np.divide(np.subtract(x, x.min(axis=0)), x.max(axis=0)-x.min(axis=0))
array([[0.52212361, 1. , 1. , 0.65700132],
[1. , 0.26245187, 0.05349413, 0.79326663],
[0.98042871, 0.06934923, 0.93899483, 0.06381829],
[0.46844205, 0. , 0.98699461, 0.24507946],
[0.40730168, 0.16851918, 0.1115184 , 1. ],
[0. , 0.7239974 , 0. , 0. ]])
The max value of each column is mapped to 1, the min value of each column is mapped to 0 an the intermediate values have are linearly mapped between 0 and 1

multiplying a 1D array by items in a 3D array

I want to ask a question about multiplying items in a 1D array with items returned from a function that are a matrix in the form of a 3D array.
I have the following array of numbers named mass_array:
array([12.0107 , 1.00794, 12.0107 , 1.00794, 12.0107 , 1.00794,
12.0107 , 1.00794, 12.0107 , 1.00794, 12.0107 , 1.00794])
and the following 3D array named coordinate_array:
array([[ 0. , 1.40272, 0. ],
[ 0. , 2.49029, 0. ],
[-1.21479, 0.70136, 0. ],
[-2.15666, 1.24515, 0. ],
[-1.21479, -0.70136, 0. ],
[-2.15666, -1.24515, 0. ],
[ 0. , -1.40272, 0. ],
[ 0. , -2.49029, 0. ],
[ 1.21479, -0.70136, 0. ],
[ 2.15666, -1.24515, 0. ],
[ 1.21479, 0.70136, 0. ],
[ 2.15666, 1.24515, 0. ]])
I am going to perform a calculation on each of these lines (which correspond to an atom on Benzene) to return a 3x3 matrix using a function called buildi, which performs calculations on a 1x3 matrix.
I want to multiply each corresponding item in mass_array by the result of the buildi function with its corresponding line on coordinate_array:
e.g.
for line 1 of both arrays multiplied together:
12.0107 * buildi([ 0. , 1.40272, 0. ])
and then for line 2 of both arrays:
1.00794 * buildi([ 0. , 2.49029, 0. ])
all the way down to the very last line,
1.00794 * buildi([ 2.15666, 1.24515, 0. ])
and add the results of each of these multiplications to a final array.
My attempt at doing this ended up as such:
def inertia_matrix(array1, array2):
inertia_molecule = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
for atom in array2:
inertia_molecule = inertia_molecule + buildi(atom)
print(inertia_molecule)
The problem, however, is that I can't 'map' the molecular weight to the corresponding line in the for loop.
My intention was to attempt something like:
for atom in array2 and weight in array1:
inertia_molecule = inertia_molecule + weight*buildi(atom)
but I couldn't work anything out that would fit such a purpose.
I attempted to use the zip function but I couldn't make it accommodate the weight*buildi(atom) part of my code.
How can I solve this problem?
The zip function is exactly made for this usecase:
inertia_molecules = []
for mass, atom in zip(mas_array, coordinate_array):
inertia_molecules.append( mass * buildi(atom) )
Now the list inertia_molecules holds a list of all 3x3 matrices produced by the calculations.
(If you are dealing with a large list, you might want to pre-allocate the space for speed and then access the individual cells instead appending new values to the end)

SVD function returns matrices with not compatible dimensions

let us consider following matrix
2 4
1 3
0 0
0 0
creation of this matrix in python and corresponding singular value decomposition can be done in python in a simple way
A =np.array([[2,4],[1,3],[0,0],[0,0]])
u,s,v =np.linalg.svd(A)
when i typed dimensions of corresponding matrix, i got following
print(u)
print(np.diag(s))
print(v)
[-0.57604844 0.81741556 0. 0. ]
[ 0. 0. 1. 0. ]
[ 0. 0. 0. 1. ]]
[[5.4649857 0. ]
[0. 0.36596619]]
[[-0.40455358 -0.9145143 ]
[-0.9145143 0.40455358]]
therefore following code for reconstructing original matrix does not work
print(u.dot(np.dot(np.diag(s),v)))
how can i fix this problem? thanks in advance
In the formal definition of the SVD, the shape of s should be (4, 2). However NumPy's routine returns an array of singular values of shape (2,). Furthermore, np.diag() doesn't know anything about how big s "should" be in the full decomposition. It just takes an array of shape (n,) and returns a 2D array of shape (n, n). So your inner product ends up with shapes (4, 4) * (2, 2) * (2, 2), which of course fails because sizes of the first product don't make sense.
To fix this, just construct an array of the correct size for s:
>>> u, s, v = np.linalg.svd(A)
>>> true_s = np.zeros((u.shape[1], v.shape[0]))
>>> true_s[:s.size, :s.size] = np.diag(s)
>>> np.allclose(u.dot(true_s).dot(v), A)
True

Matplotlib 4D data in a 2D array

I am trying to plot a 4D array using as 4th dimension the color. Here is a sample of my matrix:
[[ 4.216 0. 1. 0. ]
[ 5.36 0. 1. 0. ]
[ 5.374 0. 2. 0. ]
...,
[ 0.294 0. 1. 0. ]
[ 0.314 0. 2. 0. ]
[ 0.304 0. 1. 0. ]]
4th column only contains values 0, 1 and 2.
So when I try to plot it using this script:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(data[:,0],data[:,1],data[:,2], c=data[:,3], cmap=plt.hot())
plt.show()
I am getting this error:
TypeError: can't multiply sequence by non-int of type 'float'
This isn't a 4D array. It's a 2D array with 4 columns (the 2 dimensions could be referred to as "rows" and "columns"). But I see what you're trying to say—each row could be interpreted as describing a point in 4-dimensional space, with the fourth "dimension" being colour.
Two-dimensionality is actually the key to the problem. I suspect your data variable is a numpy.matrix rather than a vanilla numpy.array. A matrix is particular class of 2D-array that has various special properties, including the fact that a slice of it (for example, data[:, 0]) is still a 2-dimensional matrix object, whereas .scatter() expects each argument to be a 1-D array.
The fix is to say:
data = numpy.asarray(data)
to convert your data from a matrix to a normal array whose column slices will be 1-dimensional.
BTW: you probably meant to say cmap='hot'. The call to plt.hot() sets the default colormap (so your figure may look right, but there's a side effect) but it actually returns None.

Reading 2d arrays into a 3d array in python

I searched stackoverflow but could not find an answer to this specific question. Sorry if it is a naive question, I am a newbie to python.
I have several 2d arrays (or lists) that I would like to read into a 3d array (list) in python. In Matlab, I can simply do
for i=1:N
# read 2d array "a"
newarray(:,:,i)=a(:,:)
end
so newarray is a 3d array with "a" being the 2d slices arranged along the 3rd dimension.
Is there a simple way to do this in python?
Edit: I am currently trying the following:
for file in files:
img=mpimg.imread(file)
newarray=np.array(0.289*cropimg[:,:,0]+0.5870*cropimg[:,:,1]+0.1140*cropimg[:,:,2])
i=i+1
I tried newarray[:,:,i] and it gives me an error
NameError: name 'newarray' is not defined
Seems like I have to define newarray as a numpy array? Not sure.
Thanks!
If you're familiar with MATLAB, translating that into using NumPy is fairly straightforward.
Lets say you have a couple arrays
a = np.eye(3)
b = np.arange(9).reshape((3, 3))
print(a)
# [[ 1. 0. 0.]
# [ 0. 1. 0.]
# [ 0. 0. 1.]]
print(b)
# [[0 1 2]
# [3 4 5]
# [6 7 8]]
If you simply want to put them into another dimension, pass them both to the array constructor in an iterable (e.g. a list) like so:
x = np.array([a, b])
print(x)
# [[[ 1. 0. 0.]
# [ 0. 1. 0.]
# [ 0. 0. 1.]]
#
# [[ 0. 1. 2.]
# [ 3. 4. 5.]
# [ 6. 7. 8.]]]
Numpy is smart enough to recognize the arrays are all the same size and creates a new dimension to hold it all.
print(x.shape)
# (2, 3, 3)
You can loop through it, but if you want to apply the same operations to it across some dimensions, I would strongly suggest you use broadcasting so that NumPy can vectorize the operation and it runs a whole lot faster.
For example, across one dimension, lets multiply one slice by 2, another by 3. (If it's not a pure scalar, we need to reshape the array to the same number of dimensions to broadcast, then the size on each needs to either match the array or be 1). Note that I'm working along the 0th axis, your image is probably different. I don't have a handy image to load up to toy with
y = x * np.array([2, 3]).reshape((2, 1, 1))
print(y)
#[[[ 2. 0. 0.]
# [ 0. 2. 0.]
# [ 0. 0. 2.]]
#
# [[ 0. 3. 6.]
# [ 9. 12. 15.]
# [ 18. 21. 24.]]]
Then we can add them up
z = np.sum(y, axis=0)
print(z)
#[[ 2. 3. 6.]
# [ 9. 14. 15.]
# [ 18. 21. 26.]]
If you're using NumPy arrays, you can translate almost directly from Matlab:
for i in range(1, N+1):
# read 2d array "a"
newarray[:, :, i] = a[:, :]
Of course you'd probably want to use range(N), because arrays use 0-based indexing. And obviously you're going to need to pre-create newarray in some way, just as you'd have to in Matlab, but you can translate that pretty directly too. (Look up the zeros function if you're not sure how.)
If you're using lists, you can't do this directly—but you probably don't want to anyway. A better solution would be to build up a list of 2D lists on the fly:
newarray = []
for i in range(N):
# read 2d list of lists "a"
newarray.append(a)
Or, more simply:
newarray = [read_next_2d_list_of_lists() for i in range(N)]
Or, even better, make that read function a generator, then just:
newarray = list(read_next_2d_list_of_lists())
If you want to transpose the order of the axes, you can use the zip function for that.

Categories

Resources