I get confused by this example.
A = np.random.random((6, 4, 5))
A
A.min(axis=0)
A.min(axis=1)
A.min(axis=2)
What mins are we really computing here?
I know I can think of this array as a 6x5x4 Parallelepiped in 3D space and I know A.min(axis=0) means we go along the 0-th axis. OK, but as we go along that 0-th axis all we get is 6 "layers" which are basically rectangles of size 4x5 filled with numbers. So what min am I computing when saying A.min(axis=0) for example?!?! I am just trying to visualize it in my head.
From A.min(axis=0) I get back a 4x5 2D matrix. Why? Shouldn't I get just 6 values in a 1D array. I am walking along the 0-th axis so shouldn't I get 6 values back - one value for each of these 4x5 rectangles?
I always find this notation confusing and just don't get it, sorry.
You calculate the min across one particular axis when you are interested in maintaining the structure of the remainder axes.
The gif below may help to understand.
In this example, your result will have shape (3, 2).
That's because you are getting the smallest value along axis 0, which squeezes that dimension into only 1 value, so we don't need the dimension anymore.
Related
I am learning numpy , have a question in my mind not able to clearly visualise from where this 1 as come in shape
import numpy as np
a = np.array([ [[1],[56]] , [[8],[98]] ,[[89],[62]] ])
np.shape(a)
The output is printed as : (3 ,2 , 1)
Will be appreciated if you could represent in diagrammatic / image format
What actually the 1 means in output
Basically, that last 1 is because every number in a has brackets around it.
Formally, it's the length of your "last" or "innermost" dimension. You can take your first two dimensions and arrange a as you would a normal matrix, but note that each element itself has brackets around it - each element is itself an array:
[[ [1] [56]]
[ [8] [98]]
[[89] [62]]]
If you add an element to each innermost-array, making that third shape number get larger, it's like stacking more arrays behind this top one in 3d, where now the corresponding elements in the "behind" array are in the same innermost array as the "front" array.
Equivalently, instead of considering the first two indices to denote the regular flat matrices, you can think of the back two making the flat matrices. This is how numpy does it: try printing out an array like this: x = np.random.randint(10, size = (3,3,3)). Along the first dimension, x[0], x[1], and x[2] are printed after each other, and each one individually is formatted like a 3x3 matrix. Then the second index corresponds to the rows of each individual matrix, and the third index corresponds to the columns. Note that when you print a, there's only one column displayed - its third dimension has size 1. You can play with the definition of x to see more what's going on (change the numbers in the size argument).
An alright example of visualizing a 3d array this way is this image, found on the Wikipedia page for the Levi-Civita symbol:
Don't worry too much about what the Levi-Civita symbol actually is - just note that here, if it were a numpy array it would have shape (3,3,3) (like the x I defined above). You use three indices to specify each element, i, j, and k. i tells you the depth (blue, red, or green), j tells you the row, and k tells you the column. When numpy prints, it just lists out blue, red, then green in order.
Wee know, in axis parameter 0,1 means column and row wise maximum element index but
for 2,3 & so on what it indicates? An example code is given here. What is the output significance in this code?
When you have an array of higher dimensions you will also have new axes. For example, in a dimension 3 array (e.g. a cube) you will have 3 axes (row, column, depth).
When you pass the axis in the np.argmax you are telling numpy along which axis you want the maximum argument. 3 will throw an error because your array only has 3 axes (0, 1, 2).
Here is an article about numpy arrays axes.
I have to cluster a 3d array that looks like this
a=([[[1,2,3],[4,5,6],[7,8,9]],[[1,4,7],[2,5,9],[3,6,8]]])
Imagine that this array represents the coordinates of a triangle in a time series, so the first 2d array represents the coordinates of the vertices in the first frame, the second array represents the coordinates in the second frame and so on.
I need to cluster the position of this triangle in time, but the cluster algorithms of scikit -learn only work on 2d array. I have performed a reshape of the 3d array to obtain this
b=([[1,2,3,4,5,6,7,8,9],[1,4,7,2,5,9,3,6,8]])
but the performance of the cluster algorithms are poor (please note that the triangle is an example, I have to cluster the position of a much more complex figure so the dimensionality of the points in the 2d array is very high).
So I was wondering if there are other method to cluster a 3d array beside the reshape and dimensionality reduction techniques. I've read that converting the 3d array in a distance matrix could be a solution but I really don't know how to do this. If anyone has any kind of advice on how to do this or any other advice on how to solve this problem, I will really appreciate the help!
The clustering algorthm works with this format for a matrix: n_samples, n_features
So in your case your n_sample is your position in time and your n_features is your coordinate. I'm assuming you are trying to find the average location of your shapes across time. I would advise for this type of task to calculate the center point of your shape. Like this no matter the shape you have one point in the middle of the object to track across time. It would make a bit more sense than to try to track all corners on the object which I assume can rotate.
Hope it helps!
How to change the shape of array from ixMxNx3 to (M*N)xix3?
I have a ixMxNx3 array L. You can think of L as an array containing i images, each image has height=M, width=N, and in each pixel it has a three-dimensional vector (or rgb). Let P = M*N. I can change its shape to ixPx3 by L.reshape(i,P,3). (I hope it is really changing it to the shape I want). How do I change its shape to Pxix3? i.e. an array that contains P points, each point has i images, each image of that point has a three-dimensional vector.
How can this change of shape be accomplished?
numpy.rollaxis can shift the position of an axis in a NumPy array:
L = L.reshape([i, P, 3])
L = numpy.rollaxis(L, 1)
It takes 3 arguments, one optional. The first is the array, the second is the axis to move, and the third is confusingly documented as "The axis is rolled until it lies before this position". Basically, if you want to move the ith axis to the jth position and j<i, the third argument should be j. If j>i, the third argument should be j+1. I don't know why it works that way. The third argument defaults to 0.
A 3D label map is matrix in which every pixel (voxel) has an integer label. These values are expected to be contiguous, meaning that a segment with label k will not be fragmented.
Given such label map (segmentation), what is the fastest way to obtain the coordinates of a minimum bounding box around each segment, in Python?
I have tried the following:
Iterate through the matrix using multiindex iterator (from numpy.nditer) and construct a reverse index dictionary. This means that for every label you get the 3 coordinates of every voxel where the label is present.
For every label get the max and min of each coordinate.
The good thing is that you get all the location information in one O(N) pass. The bad thing is that I dont need this detailed information. I just need the extremities, so there might be a faster way to do this, using some numpy functions which are faster than so many list appends. Any suggestions?
The one pass through the matrix takes about 8 seconds on my machine, so it would be great to get rid of it. To give an idea of the data, there are a few hundred labels in a label map. Sizes of the label map can be 700x300x30 or 300x300x200 or something similar.
Edit: Now storing only updated max and min per coordinate for every label. This removes the need to maintain and store all these large lists (append).
If I understood your problem correctly, you have groups of voxels, and you would like to have the extremes of a group in each axis.
Let'd define:
arr: 3D array of integer labels
labels: list of labels (integers 0..labmax)
The code:
import numpy as np
# number of highest label:
labmax = np.max(labels)
# maximum and minimum positions along each axis (initialized to very low and high values)
b_first = np.iinfo('int32').min * np.ones((3, labmax + 1), dtype='int32')
b_last = np.iinfo('int32').max * np.ones((3, labmax + 1), dtype='int32')
# run through all of the dimensions making 2D slices and marking all existing labels to b
for dim in range(3):
# create a generic slice object to make the slices
sl = [slice(None), slice(None), slice(None)]
bf = b_first[dim]
bl = b_last[dim]
# go through all slices in this dimension
for k in range(arr.shape[dim]):
# create the slice object
sl[dim] = k
# update the last "seen" vector
bl[arr[sl].flatten()] = k
# if we have smaller values in "last" than in "first", update
bf[:] = np.clip(bf, None, bl)
After this operation we have six vectors giving the smallest and largest indices for each axis. For example, the bounding values along second axis of label 13 are b_first[1][13] and b_last[1][13]. If some label is missing, all corresponding b_first and b_last will be the maximum int32 value.
I tried this with my computer, and for a (300,300,200) array it takes approximately 1 sec to find the values.