Related
Most of the solutions online either concatenate two 3-dimensional arrays.
What I'm looking for is possibly an empty 3D array and then keep adding 2D arrays(each of the same dimensions) along any axis.
For example, initially, we have X as an h5 file dataset
X = [[[]]]
A = [[1, 1]
[1, 1]
[1, 1]
[1, 1]
[1, 1]]
# appending A to X
X = [[[1, 1]
[1, 1]
[1, 1]
[1, 1]
[1, 1]]]
# then we have another (5,2) array say
B = [[2, 2]
[2, 2]
[2, 2]
[2, 2]
[2, 2]]
# append B to X we get
X = [[[1, 1]
[1, 1]
[1, 1]
[1, 1]
[1, 1]],
[[2, 2]
[2, 2]
[2, 2]
[2, 2]
[2, 2]]]
It would have been easy to just stack two such 2d arrays but, I wanna keep adding 2D arrays in X, in such a way that dimensions of x and y-axis remain the same but z keeps growing.
Is this even possible in Python?
Given the following code:
import numpy as np
x = np.array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]],
[[3, 1],
[1, 5]]])
x_min = np.amin(x, axis=0)
print(x_min)
The output (x_min) is
[[1 1]
[1 4]]
Now I want to get the indices of dimension 0 of array x for the results of x_min array, it should be:
[[0 2]
[2 0]]
Which function can I use to get this indices?
Try np.argmin: np.argmin(x, axis=0)
Suppose that I have a 1*3 vector [[1,3,5]] (or a list like [1,3,5] if you with), how do I generate a 9*2 matrix: [[1,1],[1,3],[1,5],[3,1],[3,3],[3,5],[5,1],[5,3],[5,5]]?
Elements in the new matrix is the pairwise combination of elements in the original matrix.
Also, the original matrix could be with zeros, like this [[0,1],[0,3],[0,5]].
The implementation should generalise to vectors of any dimensionalities.
Many thanks!
You can use tf.meshgrid() and tf.transpose() to generate two matrices. Then reshape and concat them.
import tensorflow as tf
a = tf.constant([[1,3,5]])
A,B=tf.meshgrid(a,tf.transpose(a))
result = tf.concat([tf.reshape(B,(-1,1)),tf.reshape(A,(-1,1))],axis=-1)
with tf.Session() as sess:
print(sess.run(result))
[[1 1]
[1 3]
[1 5]
[3 1]
[3 3]
[3 5]
[5 1]
[5 3]
[5 5]]
You can use product from itertools
from itertools import product
np.array([np.array(item) for item in product([1,3,5],repeat =2 )])
array([[1, 1],
[1, 3],
[1, 5],
[3, 1],
[3, 3],
[3, 5],
[5, 1],
[5, 3],
[5, 5]])
I also come up with an answer, similar to #giser_yugang, but not using tf.meshgrid and tf.concat.
import tensorflow as tf
inds = tf.constant([1,3,5])
num = tf.shape(inds)[0]
ind_flat_lower = tf.tile(inds,[num])
ind_mat = tf.reshape(ind_flat_lower,[num,num])
ind_flat_upper = tf.reshape(tf.transpose(ind_mat),[-1])
result = tf.transpose(tf.stack([ind_flat_upper,ind_flat_lower]))
with tf.Session() as sess:
print(sess.run(result))
[[1 1]
[1 3]
[1 5]
[3 1]
[3 3]
[3 5]
[5 1]
[5 3]
[5 5]]
I wrote the following:
arr3=np.array([[[1,2,3],[1,2,3],[1,2,3],[1,2,3]],[[2,2,3],[4,2,3],[4,2,2],[2,2,2]],[[1,1,1],[1,1,1],[1,1,1],[1,1,1]]])
As I expected,
arr3[0:3,1] should return the same result as
arr3[0:3][1]:array([[2, 2, 3],[4, 2, 3],[4, 2, 2],[2, 2, 2]])
But it returns:array([[1, 2, 3],[4, 2, 3],[1, 1, 1]]).
BTW, I am using python3 in Jupyter notebook
When doing arr3[0:3,1], you are taking element from 0:3 in the first axis and then for each of those, taking the first element.
This gives a different result to taking the 0:3 in the first axis with arr3[0:3] and then taking the first array from this axis.
So in this case, the 0:3 part does nothing in either case as the array's shape is (3, 4, 3) so taking the first 3 just gives you back the same array. This does absolutely nothing in the second case, but in the first case, it does serve as essentially a place holder so that you can access the second axis, but for that you should just use a colon so: [:, some_index].
See how its the same array?
>>> arr3[0:3]
array([[[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[2, 2, 3],
[4, 2, 3],
[4, 2, 2],
[2, 2, 2]],
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]])
But then when you do arr3[:, 1] you are taking the second element from the second axis of the array so that will give you:
array([[1, 2, 3],
[4, 2, 3],
[1, 1, 1]])
whereas in the other case, you are taking the second element from the first axis of the array` so:
array([[2, 2, 3],
[4, 2, 3],
[4, 2, 2],
[2, 2, 2]])
To read further about numpy indexing, take a look at this page on scipy.
Take note of this specific description which applies directly to your problem:
When there is at least one slice (:), ellipsis (...) or np.newaxis in the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element
Let's look at our multidimensional numpy array:
import numpy as np
arr3=np.array([
[
[1,2,3],[1,2,3],[1,2,3],[1,2,3]
],[
[2,2,3],[4,2,3],[4,2,2],[2,2,2]
],[
[1,1,1],[1,1,1],[1,1,1],[1,1,1]
]
])
print(arr3[0:3,1])
That returns:
[[1 2 3]
[4 2 3]
[1 1 1]]
Which makes sense because we are fetching row numbers 1 through 3 and we are grabbing only the first column.
However, arr3[0:3][1] returns the array from row 0 to row 3 and then selects the second row (or row index 1).
Observe:
print(arr3[0:3])
Returns:
[[[1 2 3]
[1 2 3]
[1 2 3]
[1 2 3]]
[[2 2 3]
[4 2 3]
[4 2 2]
[2 2 2]]
[[1 1 1]
[1 1 1]
[1 1 1]
[1 1 1]]]
It returns the a new array (which happens to be the same as our current array because we just asked for all rows in the array). Then we ask for the second row:
print(arr3[0:3][1])
Returns:
[[2 2 3]
[4 2 3]
[4 2 2]
[2 2 2]]
I have a list
[[0, 3], [5, 1], [2, 1], [4, 5]]
which I have made into an array using numpy.array:
[[0 3]
[5 1]
[2 1]
[4 5]]
How do I sort this like a table? In particular, I want to sort by the second column in ascending order and then resolve any ties by having the first column sorted in ascending order. Thus I desire:
[[2 1]
[5 1]
[0 3]
[4 5]]
Any help would be greatly appreciated!
See http://docs.scipy.org/doc/numpy/reference/generated/numpy.lexsort.html#numpy.lexsort
Specifically in your case,
import numpy as np
x = np.array([[0,3],[5,1],[2,1],[4,5]])
x[np.lexsort((x[:,0],x[:,1]))]
outputs
array([[2,1],[5,1],[0,3],[4,5]])
You can use numpy.lexsort():
>>> a = numpy.array([[0, 3], [5, 1], [2, 1], [4, 5]])
>>> a[numpy.lexsort(a.T)]
array([[2, 1],
[5, 1],
[0, 3],
[4, 5]])
Another way of doing this - slice out the bits of data you want, get the sort indices using argsort, then use the result of that to slice your original array:
a = np.array([[0, 3], [5, 1], [2, 1], [4, 5]])
subarray = a[:,1] # 3,1,1,5
indices = np.argsort(subarray) # Returns array([1,2,0,3])
result = a[indices]
Or, all in one go:
a[np.argsort(a[:,1])]
If you want to sort using a single column only (e.g., second column), you can do something like:
from operator import itemgetter
a = [[0, 3], [5, 1], [2, 1], [4, 5]]
a_sorted = sorted(a, key=itemgetter(1))
If there are more than one key, then use numpy.lexsort() as pointed out in the other answers.