Numpy ndarray's min/max with axis variable - arrays

I'm a bit confused about how numpy's ndarray's min/max function with a given axis argument works.
import numpy as np
x = np.random.rand(2,3,4)
x.min(axis=0)
produces
array([[[0.4139181 , 0.24235588, 0.50214552, 0.38806332],
[0.63775691, 0.08142376, 0.69722379, 0.1968098 ],
[0.50496744, 0.54245416, 0.75325114, 0.67245846]],
[[0.79760899, 0.35819981, 0.5043491 , 0.75274284],
[0.54778544, 0.5597848 , 0.52325408, 0.66775091],
[0.71255276, 0.85835137, 0.60197253, 0.33060771]]])
array([[0.4139181 , 0.24235588, 0.50214552, 0.38806332],
[0.54778544, 0.08142376, 0.52325408, 0.1968098 ],
[0.50496744, 0.54245416, 0.60197253, 0.33060771]])
a 3x4 numpy array. I was thinking it would produce a size 2 array with the minimum for x[0] and x[1].
Can someone explain how this min function is working?

When you do x.min(axis=0), you request the min to be computed along the axis 0, which means this dimension is aggregated into a single value and thus the output has a (3,4) shape.
What you want is to compute the min on the combined axes 1 and 2:
x.min(axis=(1,2))
# array([0.38344152, 0.0202184 ])
You can also first reshape the array to combine those two dimensions, then compute the min along this new dimension (here, 1):
x.reshape(2,-1).min(axis=1)
# array([0.38344152, 0.0202184 ])
intermediate, reshaped, array:
x.reshape(2,-1)
array([[0.5488135 , 0.71518937, 0.60276338, 0.54488318, 0.4236548 ,
0.64589411, 0.43758721, 0.891773 , 0.96366276, 0.38344152,
0.79172504, 0.52889492],
[0.56804456, 0.92559664, 0.07103606, 0.0871293 , 0.0202184 ,
0.83261985, 0.77815675, 0.87001215, 0.97861834, 0.79915856,
0.46147936, 0.78052918]])
used input:
np.random.seed(0)
x = np.random.rand(2,3,4)

Related

reshaping 3 column numpy array

i have the following numpy array extracted from a dataframe that i want to reshape
Extraction
x = c_df['x'].values
y = c_df['y'].values
z = c_df['z'].values
convert to array
x_y_z = np.array([x, y, z])
x_y_z
Array looks like this
array([[748260.27757, 748262.56478, 748263.52455, ..., 730354.86406,
730374.75 , 730388.45066],
[333346.25 , 333308.43521, 333296.25 , ..., 331466.13593,
331453.84365, 331446.25 ],
[ 2840. , 2840. , 2840. , ..., 2400. ,
2400. , 2400. ]])
basically i want to reshape it to be able to plot using plt.contourf which required Z to be 2D array
so i assume the array needs to be reshaped to something like
YYYYYYYYYY
Xzzzzzzzzzz
Xzzzzzzzzzz
Xzzzzzzzzzz
Xzzzzzzzzzz
is my assumption correct? if yes how to reshape the array.
If I understand you correctly Numpy Mgrid should be able to help you. However you might want some more explanation which can be found on this thread.
For the next time you can make it easier if you provide a simplified example of your problem.

Create a 2-D Array From a Group of 1-D Arrays of Different Lengths in Python

I have 2 1-D arrays that I have combined into a single 1-D array and would like to combine them into a 2-D array with 3 columns consisting of the two arrays and the newly created combined array. Ultimately, the objective is to plot all three 1-D arrays on a single chart using Plotly. The values are datetime but I will use integers here for the sake of simplicity.
import numpy as np
a = np.array([1,3,4,5,7,9])
b = np.array([2,4,6,8])
c = np.array([1,2,3,4,5,6,7,8,9])
# The created array should be 9 rows and 3 columns that looks like:
abc = np.array([1,0,1],[0,2,2],[3,0,3],[4,4,4],[5,0,5],[0,6,6],[7,0,7],[0,8,8],[9,0,9])
Essentially, array abc is the c column repeated 3 times with zeros where there are missing values for a or b. I would prefer to do this in Numpy but am open to alternatives as well. In addition, the zeros don't have to be present and can be substituted with NaN, Null, etc. The questions I've reviewed seem to suggest that there is no way to combine arrays of different lengths but I'm certain there must be a way of combining the arrays by extending the shorter ones using indexing. I'm just having trouble getting from here to there. Any help would be greatly appreciated.
Pure numpy approach:
import numpy as np
a = np.array([1,3,4,5,7,9])
b = np.array([2,4,6,8])
c = np.array([1,2,3,4,5,6,7,8,9])
abc = np.zeros((10, 3))
# change to a loop, if you like
abc[a, 0] = a
abc[b, 1] = b
abc[c, 2] = c
print(abc[1:])
prints:
[[1. 0. 1.]
[0. 2. 2.]
[3. 0. 3.]
[4. 4. 4.]
[5. 0. 5.]
[0. 6. 6.]
[7. 0. 7.]
[0. 8. 8.]
[9. 0. 9.]]

Inconsistent Results - Jupyter Numpy & Transpose

enter image description here
I am getting odd behavior with Jupyter/Numpy/Tranpose()/1D Arrays.
I found another post where transpose() will not transpose a 1D array, but in previous Jupyter notebooks, it does.
I have an example where it is inconsistent, and I do not understand:
Please see the picture attached of my jupyter notebook if 2 more or less identical arrays with 2 different outputs.
It seems it IS and IS NOT transposing the 1D array. Inconsistency is bad
outputs is (1000,) and (1,1000), why does this occur?
# GENERATE WAVEORM:
#---------------------------------------------------------------------------------------------------
N = 1000
fxc = []
fxn = []
for t in range(0,N):
fxc.append(A1*m.sin(2.0*pi*50.0*dt*t) + A2*m.sin(2.0*pi*120.0*dt*t))
fxn.append(A1*m.sin(2.0*pi*50.0*dt*t) + A2*m.sin(2.0*pi*120.0*dt*t) + 5*np.random.normal(u,std,size=1))
#---------------------------------------------------------------------------------------------------
# TAKE TRANSPOSE:
#---------------------------------
fc = np.transpose(np.array(fxc))
fn = np.transpose(np.array(fxn))
#---------------------------------
# PRINT DIMENSION:
#---------------------------------
print(fc.shape)
print(fn.shape)
#---------------------------------
Remove size=1 from your call to numpy.random.normal. Then it will return a scalar instead of a 1-d array of length 1.
For example,
In [2]: np.random.normal(0, 3, size=1)
Out[2]: array([0.47058288])
In [3]: np.random.normal(0, 3)
Out[3]: 4.350733438283539
Using size=1 in your code is a problem, because it results in fxn being a list of 1-d arrays (e.g. something like [[0.123], [-.4123], [0.9455], ...]. When NumPy converts that to an array, it has shape (N, 1). Transposing such an array results in the shape (1, N).
fxc, on the other hand, is a list of scalars (e.g. something like [0.123, 0.456, ...]). When converted to a NumPy array, it will be a 1-d array with shape (N,). NumPy's transpose operation swaps dimensions, but it does not create new dimensions, so transposing a 1-d array does nothing.

Extract array dimensions in Julia

Given a vector A defined in Matlab by:
A = [ 0
0
1
0
0 ];
we can extract its dimensions using:
size(A);
Apparently, we can achieve the same things in Julia using:
size(A)
Just that in Matlab we are able to extract the dimensions in a vector, by using:
[n, m] = size(A);
irrespective to the fact whether A is one or two-dimensional, while in Julia A, size (A) will return only one dimension if A has only one dimension.
How can I do the same thing as in Matlab in Julia, namely, extracting the dimension of A, if A is a vector, in a vector [n m]. Please, take into account that the dimensions of A might vary, i.e. it could have sometimes 1 and sometimes 2 dimensions.
A = zeros(3,5)
sz = size(A)
returns a tuple (3,5). You can refer to specific elements like sz[1]. Alternatively,
m,n = size(A,1), size(A,2)
This works even if A is a column vector (i.e., one-dimensional), returning a value of 1 for n.
This will achieve what you're expecting:
n, m = size(A); #or
(n, m) = size(A);
If size(A) is a one dimensional Tuple, m will not be assigned, while n will receive length(A). Just be sure to catch that error, otherwise your code may stop if running from a script.

Despite many examples online, I cannot get my MATLAB repmat equivalent working in python

I am trying to do some numpy matrix math because I need to replicate the repmat function from MATLAB. I know there are a thousand examples online, but I cannot seem to get any of them working.
The following is the code I am trying to run:
def getDMap(image, mapSize):
newSize = (float(mapSize[0]) / float(image.shape[1]), float(mapSize[1]) / float(image.shape[0]))
sm = cv.resize(image, (0,0), fx=newSize[0], fy=newSize[1])
for j in range(0, sm.shape[1]):
for i in range(0, sm.shape[0]):
dmap = sm[:,:,:]-np.array([np.tile(sm[j,i,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))])
return dmap
The function getDMap(image, mapSize) expects an OpenCV2 HSV image as its image argument, which is a numpy array with 3 dimensions: [:,:,:]. It also expects a tuple with 2 elements as its imSize argument, of course making sure the function passing the arguments takes into account that in numpy arrays the rows and colums are swapped (not: x, y, but: y, x).
newSize then contains a tuple containing fracions that are used to resize the input image to a specific scale, and sm becomes a resized version of the input image. This all works fine.
This is my goal:
The following line:
np.array([np.tile(sm[i,j,:], (len(sm[0]), len(sm[1]))) for k in xrange(len(sm[2]))]),
should function equivalent to the MATLAB expression:
repmat(sm(j,i,:),[size(sm,1) size(sm,2)]),
This is my problem:
Testing this, an OpenCV2 image with dimensions 800x479x3 is passed as the image argument, and (64, 48) (a tuple) is passed as the imSize argument.
However when testing this, I get the following ValueError:
dmap = sm[:,:,:]-np.array([np.tile(sm[i,j,:], (len(sm[0]),
len(sm[1]))) for k in xrange(len(sm[2]))])
ValueError: operands could not be broadcast together with
shapes (48,64,3) (64,64,192)
So it seems that the array dimensions do not match and numpy has a problem with that. But my question is what? And how do I get this working?
These 2 calculations match:
octave:26> sm=reshape(1:12,2,2,3)
octave:27> x=repmat(sm(1,2,:),[size(sm,1) size(sm,2)])
octave:28> x(:,:,2)
7 7
7 7
In [45]: sm=np.arange(1,13).reshape(2,2,3,order='F')
In [46]: x=np.tile(sm[0,1,:],[sm.shape[0],sm.shape[1],1])
In [47]: x[:,:,1]
Out[47]:
array([[7, 7],
[7, 7]])
This runs:
sm[:,:,:]-np.array([np.tile(sm[0,1,:], (2,2,1)) for k in xrange(3)])
But it produces a (3,2,2,3) array, with replication on the 1st dimension. I don't think you want that k loop.
What's the intent with?
for i in ...:
for j in ...:
data = ...
You'll only get results from the last iteration. Did you want data += ...? If so, this might work (for a (N,M,K) shaped sm)
np.sum(np.array([sm-np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
z = np.array([np.tile(sm[i,j,:], (N,M,1)) for i in xrange(N) for j in xrange(M)]),axis=0)
np.sum(sm - z, axis=0) # let numpy broadcast sm
Actually I don't even need the tile. Let broadcasting do the work:
np.sum(np.array([sm-sm[i,j,:] for i in xrange(N) for j in xrange(M)]),axis=0)
I can get rid of the loops with repeat.
sm1 = sm.reshape(N*M,L) # combine 1st 2 dim to simplify repeat
z1 = np.repeat(sm1, N*M, axis=0).reshape(N*M,N*M,L)
x1 = np.sum(sm1 - z1, axis=0).reshape(N,M,L)
I can also apply broadcasting to the last case
x4 = np.sum(sm1-sm1[:,None,:], 0).reshape(N,M,L)
# = np.sum(sm1[None,:,:]-sm1[:,None,:], 0).reshape(N,M,L)
With sm I have to expand (and sum) 2 dimensions:
x5 = np.sum(np.sum(sm[None,:,None,:,:]-sm[:,None,:,None,:],0),1)
len(sm[0]) and len(sm[1]) are not the sizes of the first and second dimensions of sm. They are the lengths of the first and second row of sm, and should both return the same value. You probably want to replace them with sm.shape[0] and sm.shape[1], which are equivalent to your Matlab code, although I am not sure that it will work as you expect it to.

Resources