Multiple numpy arrays to bytes - python

Input/Output:
[array([[ 2.120417 , -13.725279 ],
[ 2.066555 , -13.953174 ]], dtype=float32)
array([[ 1.952603, 6.800025],
[ 1.952603, 6.800025]], dtype=float32)
b"\x40\x07\xb4\xea\xc1\x5b\x9a\xbe\x3f\xf9\xee\xe5\x40\xd9\x99\xce\x40\x04\x42\x70\xc1\x5f\x40\x33\x3f\xf9\xee\xe5\x40\xd9\x99\xce"
Each array contains multiple x, y coordinates (floats). I want to go through one element in an array (one element contains a set of x, y coords) and then the next array at the same index, then after all arrays have been gone through the first index, then the next.

IIUC, you can hstack and ravel:
np.hstack([arr1, arr2, arr3]).ravel()
Output:
array([ 0, 1, 4, 5, 8, 9, 2, 3, 6, 7, 10, 11])
Used input ([arr1, arr2, arr3]):
[array([[0, 1],
[2, 3]]),
array([[4, 5],
[6, 7]]),
array([[ 8, 9],
[10, 11]])]

Related

transfer 3D NumPy array into a 2D NumPy array

let's say a NumPy array
a = np.array(
[[[1,2,3],
[4,5,6]],
[[7,8,9],
[10,11,12]]])
the shape will be like (2,2,3).
I'd like to make it look like this:
a = np.array(
[[1,2,3],
[7,8,9],
[4,5,6],
[10,11,12]]
)
which shape will be like (4,3).
if I use reshape, it will look like as:
a = np.array(
[[1,2,3],
[4,5,6],
[7,8,9],
[10,11,12]]
)
Which is NOT what I want. How to do this?
One way using numpy.stack and vstack:
np.vstack(np.stack(a, 1))
Output:
array([[ 1, 2, 3],
[ 7, 8, 9],
[ 4, 5, 6],
[10, 11, 12]])
By using indexing method, an idx list could be created that specifies which indices of the ex a must be placed as which indices in the new one i.e. idx is a rearranging list:
idx = [0, 2, 1, 3]
a = a.reshape(4, 3)[idx]
a is firstly reshaped to the intended shape, which is (4,3), and then rearranged by the idx. idx[1] = 2 is showing that value in index = 2 of the ex a will be replaced to index = 1 in the new a.
Here is a more pythonic version of your problem.
This uses concatenate so append the rows of your array.
a = np.array(
[[[1,2,3],
[4,5,6]],
[[7,8,9],
[10,11,12]]]
)
def transform_2d(a_arr):
nrow = len(a[:])
all = a_arr[:,0]
for i in range(1,nrow):
all = np.concatenate((all, a_arr[:,i] ))
return all
print(transform_2d(a))
First use transpose (or swapaxes) to bring the desire rows together:
In [268]: a.transpose(1,0,2)
Out[268]:
array([[[ 1, 2, 3],
[ 7, 8, 9]],
[[ 4, 5, 6],
[10, 11, 12]]])
then the reshape follows:
In [269]: a.transpose(1,0,2).reshape(-1,3)
Out[269]:
array([[ 1, 2, 3],
[ 7, 8, 9],
[ 4, 5, 6],
[10, 11, 12]])

Select from a 3-dimensional array with a 2-dimensional array

I have two arrays:
a: a 3-dimensional source array (N x M x 2)
b: a 2-dimensional index array (N x M) containing 0 and 1s.
I want to use the indices in b to select the corresponding elements of a in its third dimension. The resulting array should have the dimensions N x M. Here is the example as code:
import numpy as np
a = np.array( # dims: 3x3x2
[[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]]]
)
b = np.array( # dims: 3x3
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]
)
# select the elements in a according to b
# to achieve this result:
desired = np.array(
[[ 1, 3, 5],
[ 7, 9, 11],
[13, 15, 17]]
)
At first, I thought this must have a simple solution but I could not find one at all. Since I would like to port it to tensorflow, I would appreciate if somebody knows a numpy-type solution for this.
Edit: The third dimension of a might contain more than two elements. Hence, b might also contain indices different from 0 and 1 - it is not a boolean mask.
We can use np.where for this:
np.where(b, a[:, :, 1], a[:, :, 0])
Output:
array([[ 1, 3, 5],
[ 7, 9, 11],
[13, 15, 17]])
As #jdehesa sugests, we can use np.ogrid to obtain the indices for the first two axes:
ax0, ax1 = np.ogrid[:b.shape[0], :b.shape[1]]
And then we can use b to directly index along the last axis. Note that ax0 and ax1 will be broadcast to the shape of b:
desired = a[ax0, ax1 ,b]
print(desired)
array([[ 1, 3, 5],
[ 7, 9, 11],
[13, 15, 17]])
I added some solutions for tensorflow.
import tensorflow as tf
a = tf.constant([[[ 0, 1],[ 2, 3],[ 4, 5]],
[[ 6, 7],[ 8, 9],[10, 11]],
[[12, 13],[14, 15],[16, 17]]],dtype=tf.float32)
b = tf.constant([[1, 1, 1],[1, 1, 1],[1, 1, 1]],dtype=tf.int32)
# 1. use tf.gather_nd
colum,row = tf.meshgrid(tf.range(a.shape[0]),tf.range(a.shape[1]))
idx = tf.stack([row, colum, b], axis=-1) # Thanks for #jdehesa's suggestion
result1 = tf.gather_nd(a,idx)
# 2. use tf.reduce_sum
mask = tf.one_hot(b,depth=a.shape[-1],dtype=tf.float32)
result2 = tf.reduce_sum(a*mask,axis=-1)
# 3. use tf.boolean_mask
mask = tf.one_hot(b,depth=a.shape[-1],dtype=tf.float32)
result3 = tf.reshape(tf.boolean_mask(a,mask),b.shape)
with tf.Session() as sess:
print('method 1: \n',sess.run(result1))
print('method 2: \n',sess.run(result2))
print('method 3: \n',sess.run(result3))
method 1:
[[ 1. 3. 5.]
[ 7. 9. 11.]
[13. 15. 17.]]
method 2:
[[ 1. 3. 5.]
[ 7. 9. 11.]
[13. 15. 17.]]
method 3:
[[ 1. 3. 5.]
[ 7. 9. 11.]
[13. 15. 17.]]
You can use np.take_along_axis:
import numpy as np
a = np.array(
[[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]]])
b = np.array(
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
print(np.take_along_axis(a, b[..., np.newaxis], axis=-1)[..., 0])
# [[ 1 3 5]
# [ 7 9 11]
# [13 15 17]]

how can I do 2d 3d multiplication

I have two array one is 3d :
np.array([[[1,2,3],[3,2,1]],
[[2,3,2],[1,2,5]]])
and one 2d array :
np.array([[2,3],
[3,4]])
and I want to multiply these two to get
np.array([[[2,4,6],[9,6,3]],
[[6,9,6],[4,8,20]]])
How can I do this using numpy package? Thanks.
Use broadcasting:
In [129]: b[:,:,None] * a
Out[129]:
array([[[ 2, 4, 6],
[ 9, 6, 3]],
[[ 6, 9, 6],
[ 4, 8, 20]]])
With following names:
main = np.array([[[1,2,3],[3,2,1]],
[[2,3,2],[1,2,5]]])
fac = np.array([[2,3],
[3,4]])
It can managed with iteration as follows:
a1 = []
for i in [0,1]:
a2 = []
for j in [0,1]:
a2.append(main[i][j]*fac[i][j])
a1.append(a2)
print(a1)
Output:
[[array([2, 4, 6]), array([9, 6, 3])], [array([6, 9, 6]), array([ 4, 8, 20])]]

Numpy assignment like 'numpy.take'

Is it possible to assign to a numpy array along the lines of how the take functionality works?
E.g. if I have a an array a, a list of indices inds, and a desired axis, I can use take as follows:
import numpy as np
a = np.arange(12).reshape((3, -1))
inds = np.array([1, 2])
print(np.take(a, inds, axis=1))
[[ 1 2]
[ 5 6]
[ 9 10]]
This is extremely useful when the indices / axis needed may change at runtime.
However, numpy does not let you do this:
np.take(a, inds, axis=1) = 0
print(a)
It looks like there is some limited (1-D) support for this via numpy.put, but I was wondering if there was a cleaner way to do this?
In [222]: a = np.arange(12).reshape((3, -1))
...: inds = np.array([1, 2])
...:
In [223]: np.take(a, inds, axis=1)
Out[223]:
array([[ 1, 2],
[ 5, 6],
[ 9, 10]])
In [225]: a[:,inds]
Out[225]:
array([[ 1, 2],
[ 5, 6],
[ 9, 10]])
construct an indexing tuple
In [226]: idx=[slice(None)]*a.ndim
In [227]: axis=1
In [228]: idx[axis]=inds
In [229]: a[tuple(idx)]
Out[229]:
array([[ 1, 2],
[ 5, 6],
[ 9, 10]])
In [230]: a[tuple(idx)] = 0
In [231]: a
Out[231]:
array([[ 0, 0, 0, 3],
[ 4, 0, 0, 7],
[ 8, 0, 0, 11]])
Or for a[inds,:]:
In [232]: idx=[slice(None)]*a.ndim
In [233]: idx[0]=inds
In [234]: a[tuple(idx)]
Out[234]:
array([[ 4, 0, 0, 7],
[ 8, 0, 0, 11]])
In [235]: a[tuple(idx)]=1
In [236]: a
Out[236]:
array([[0, 0, 0, 3],
[1, 1, 1, 1],
[1, 1, 1, 1]])
PP's suggestion:
def put_at(inds, axis=-1, slc=(slice(None),)):
return (axis<0)*(Ellipsis,) + axis*slc + (inds,) + (-1-axis)*slc
To be used as in a[put_at(ind_list,axis=axis)]
I've seen both styles on numpy functions. This looks like one used for extend_dims, mine was used in apply_along/over_axis.
earlier thoughts
In a recent take question I/we figured out that it was equivalent to arr.flat[ind] for some some raveled index. I'll have to look that up.
There is an np.put that is equivalent to assignment to the flat:
Signature: np.put(a, ind, v, mode='raise')
Docstring:
Replaces specified elements of an array with given values.
The indexing works on the flattened target array. `put` is roughly
equivalent to:
a.flat[ind] = v
Its docs also mention place and putmask (and copyto).
numpy multidimensional indexing and the function 'take'
I commented take (without axis) is equivalent to:
lut.flat[np.ravel_multi_index(arr.T, lut.shape)].T
with ravel:
In [257]: a = np.arange(12).reshape((3, -1))
In [258]: IJ=np.ix_(np.arange(a.shape[0]), inds)
In [259]: np.ravel_multi_index(IJ, a.shape)
Out[259]:
array([[ 1, 2],
[ 5, 6],
[ 9, 10]], dtype=int32)
In [260]: np.take(a,np.ravel_multi_index(IJ, a.shape))
Out[260]:
array([[ 1, 2],
[ 5, 6],
[ 9, 10]])
In [261]: a.flat[np.ravel_multi_index(IJ, a.shape)] = 100
In [262]: a
Out[262]:
array([[ 0, 100, 100, 3],
[ 4, 100, 100, 7],
[ 8, 100, 100, 11]])
and to use put:
In [264]: np.put(a, np.ravel_multi_index(IJ, a.shape), np.arange(1,7))
In [265]: a
Out[265]:
array([[ 0, 1, 2, 3],
[ 4, 3, 4, 7],
[ 8, 5, 6, 11]])
Use of ravel is unecessary in this case but might useful in others.
I have given an example for use of
numpy.take in 2 dimensions. Perhaps you can adapt that to your problem
You can juste use indexing in this way :
a[:,[1,2]]=0

How to add a dimension to a numpy array in Python

I have an array that is size (214, 144). I need it to be (214,144,1) is there a way to do this easily in Python? Basically the dimensions are supposed to be (Days, Times, Stations). Since I only have 1 station's data that dimension would be a 1. However if I could also make the code flexible enough work for say 2 stations that would be great (e.g. changing the dimension size from (428,288) to (214,144,2)) that would be great!
You could use reshape:
>>> a = numpy.array([[1,2,3,4,5,6],[7,8,9,10,11,12]])
>>> a.shape
(2, 6)
>>> a.reshape((2, 6, 1))
array([[[ 1],
[ 2],
[ 3],
[ 4],
[ 5],
[ 6]],
[[ 7],
[ 8],
[ 9],
[10],
[11],
[12]]])
>>> _.shape
(2, 6, 1)
Besides changing the shape from (x, y) to (x, y, 1), you could use (x, y/n, n) as well, but you may want to specify the column order depending on the input:
>>> a.reshape((2, 3, 2))
array([[[ 1, 2],
[ 3, 4],
[ 5, 6]],
[[ 7, 8],
[ 9, 10],
[11, 12]]])
>>> a.reshape((2, 3, 2), order='F')
array([[[ 1, 4],
[ 2, 5],
[ 3, 6]],
[[ 7, 10],
[ 8, 11],
[ 9, 12]]])
1) To add a dimension to an array a of arbitrary dimensionality:
b = numpy.reshape (a, list (numpy.shape (a)) + [1])
Explanation:
You get the shape of a, turn it into a list, concatenate 1 to that list, and use that list as the new shape in a reshape operation.
2) To specify subdivisions of the dimensions, and have the size of the last dimension calculated automatically, use -1 for the size of the last dimension. e.g.:
b = numpy.reshape(a, [numpy.size(a,0)/2, numpy.size(a,1)/2, -1])
The shape of b in this case will be [214,144,4].
(obviously you could combine the two approaches if necessary):
b = numpy.reshape (a, numpy.append (numpy.array (numpy.shape (a))/2, -1))

Categories