concentrate 2 arrays of vectors - python-3.x

Hi I have 2 arrays of vectors:
A=np.array([[5,62,7],[5,62,7],[5,62,7]])
B=np.array([[1,2,3],[1,2,3],[1,2,3]])
and I would like to concentrate them like that:
C=[[[5,62,7], [1,2,3]],
[[5,62,7], [1,2,3]],
[[5,62,7], [1,2,3]]]

The newish stack makes this easy:
In [130]: A=np.array([[5,62,7],[5,62,7],[5,62,7]])
...: B=np.array([[1,2,3],[1,2,3],[1,2,3]])
...:
In [131]: np.stack((A,B), axis=1)
Out[131]:
array([[[ 5, 62, 7],
[ 1, 2, 3]],
[[ 5, 62, 7],
[ 1, 2, 3]],
[[ 5, 62, 7],
[ 1, 2, 3]]])
It adds an extra dimension to each of the arrays, and then concatenates. With axis=0 is behave just like np.array.
np.array((A,B)).transpose(1,0,2)
joins them on a new 1st axis, and then moves it over.

hstack().reshape() to the rescue:
import numpy as np
A=np.array([[5,62,7],[5,62,7],[5,62,7]])
B=np.array([[1,2,3],[1,2,3],[1,2,3]])
c = np.hstack((A,B)).reshape(3,2,3)
print(c)
Output:
[[[ 5 62 7] [ 1 2 3]]
[[ 5 62 7] [ 1 2 3]]
[[ 5 62 7] [ 1 2 3]]]
hstack
reshape

Related

Concatenating 3D arrays with different dimensions on axis 2

I'm attempting to put together a number of 3D arrays with the same size on the first two dimensions but differing sizes on the 3rd dimensions. I'm using numpy.hstack().
import numpy as np
first = np.array([[[1,2], [3,4]],
[[5,6], [7,8]],
[[9,10],[11,12]]])
second = np.array([[[88],[88]],
[[88],[88]],
[[88],[88]]])
output = np.hstack((first,second))
print (output)
This results in an error:
Exception has occurred: ValueError
all the input array dimensions for the concatenation axis must match exactly, but along dimension 2, the array at index 0 has size 2 and the array at index 1 has size 1all the input array dimensions for the concatenation axis must match exactly, but along dimension 2, the array at index 0 has size 2 and the array at index 1 has size 1
Now, if I try this on two 2D arrays with a mismatched second dimension, np.hstack() has no trouble. For instance:
import numpy as np
first= np.array([[1,2],[3,4],[5,6]])
second= np.array([[88],[88],[88]])
output = np.hstack((first,second))
print (output)
outputs, as expected:
[[ 1 2 88]
[ 3 4 88]
[ 5 6 88]]
The result I'm going for with the 3D concatenation is:
[[[ 1 2 88],[ 3 4 88]]
[[ 5 6 88],[ 7 8 88]]
[[ 9 10 88],[ 11 12 88]]]
Am I going about it the right way? Is there an alternative? Thanks for your help.
np.concatenate is what you're looking for:
>>> import numpy as np
>>> first = np.arange(1, 13).reshape(3, 2, 2); first
array([[[ 1, 2],
[ 3, 4]],
[[ 5, 6],
[ 7, 8]],
[[ 9, 10],
[11, 12]]])
>>> second = np.repeat(88, 6).reshape(3, 2, 1); second
array([[[88],
[88]],
[[88],
[88]],
[[88],
[88]]])
>>> np.concatenate((first, second), axis=2)
array([[[ 1, 2, 88],
[ 3, 4, 88]],
[[ 5, 6, 88],
[ 7, 8, 88]],
[[ 9, 10, 88],
[11, 12, 88]]])

How to use list comprehensions for this?

I want to take input of 2 numbers: the number of rows and the number of columns. I then want to use these to output a matrix numbered sequentially. I want to do this using a list comprehension. The following is a possible output.
>>>> my_matrix = matrix_fill(3, 4)
>>>> my_matrix
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
I am using the following code to output a sequentially numbered list:
def matrix_fill(num_rows, num_col):
list=[i for i in range(num_col)]
return (list)
I cannot, however, figure out how to make the sequential list of numbers break into the separate lists as shown in the output based on num_rows.
I don't think you need itertools for that. The range function can take a step as a parameter. Like this:
def matrix_fill(rows,cols):
return [[x for x in range(1,rows*cols+1)][i:i+cols] for i in range(0,rows*cols,cols)]
And then it works as expected.
>>> matrix_fill(3,4)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
Let's break this down a little bit and understand what's happening.
>>> [x for x in range(1,3*4+1)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
So what we want to do is to get a new slice every four elements.
>>> [x for x in range(1,3*4+1)][0:4]
[1, 2, 3, 4]
>>> [x for x in range(1,3*4+1)][4:8]
[5, 6, 7, 8]
>>> [x for x in range(1,3*4+1)][8:12]
[9, 10, 11, 12]
So we want to iterate over the elements of the list[x for x in range(1,3*4+1)] of length "rows*cols" ( 3 * 4 ), create a new slice every "cols" number of elements, and group these slices under a single list. Therefore, [[x for x in range(1,rows*cols+1)][i:i+cols] for i in range(0,rows*cols,cols)] is a suitable expression.
Nest a list comprehension inside another one, use itertools.count() to generate the sequence:
import itertools
rows = 3
cols = 4
count_gen = itertools.count() # pass start=1 if you need the sequence to start at 1
my_matrix = [[next(count_gen) for c in range(cols)] for r in range(rows)]
print(my_matrix)
# prints: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
# As a function
def matrix_fill(rows, cols):
count_gen = itertools.count()
return [[next(count_gen) for c in range(cols)] for r in range(rows)]
If you used the numpy module, the method is extremely simple, with no list comprehension needed.
my_matrix = np.arange(1, 13).reshape(3,4)
Printing the variable my_matrix shows
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]

Transform a column into specific rows using numpy

I am trying to extract a column and arrange into multiple rows.
My Input: data
-2.74889,1.585,223.60
-2.74889,1.553,228.60
-2.74889,1.423,246.00
-2.74889,1.236,249.10
-2.74889,0.928,243.80
-2.74889,0.710,242.20
-2.74889,0.558,243.50
...
...
...
k = np.reshape(data[:,2], (2,10))
Output:
[[ 223.6 228.6 246. 249.1 243.8 242.2 243.5 244. 244.8
245.2 ]
[ 224.6 230. 250.7 249.3 244.4 242.1 242.8 243.8 244.7
245.1 ]]
My question is how to add square brackets for each number(for example 223.6) and remain them in 1 row?
Thanks,
Prasad.
It's not entirely clear what you mean, but perhaps it's something like this?
>>> import numpy as np
>>> data = np.arange(30).reshape(10,3)
>>> data
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]])
>>> data[:, 2, None]
array([[ 2],
[ 5],
[ 8],
[11],
[14],
[17],
[20],
[23],
[26],
[29]])
You need to expand the dimensions of the array when you reshape.
Setup
x = np.arange(60).reshape(20, 3)
reshape with an additional dimension
x[:, 2].reshape((-1, 10, 1))
expand_dims with axis=2
np.expand_dims(x[:, 2].reshape(-1, 10), axis=2)
atleast_3d
np.atleast_3d(x[:, 2].reshape(-1, 10))
All three produce:
array([[[ 2],
[ 5],
[ 8],
[11],
[14],
[17],
[20],
[23],
[26],
[29]],
[[32],
[35],
[38],
[41],
[44],
[47],
[50],
[53],
[56],
[59]]])

Transpose 3D Numpy Array

Trying to transpose each numpy array in my numpy array.
Here is an example of what I want:
A:
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
A Transpose:
[[[ 1 4]
[ 2 5]
[ 3 6]]
[[ 7 10]
[ 8 11]
[ 9 12]]]
Tried doing this using np.apply_along_axis function but was not getting the correct results.I am trying to apply this to a very large array and any help would be greatly appreciated!
A=np.arange(1,13).reshape(2,2,3)
A=np.apply_along_axis(np.transpose, 0, A)
You need to swap the second and third axises, for which you can use either np.swapaxes:
A.swapaxes(1,2)
#array([[[ 1, 4],
# [ 2, 5],
# [ 3, 6]],
# [[ 7, 10],
# [ 8, 11],
# [ 9, 12]]])
or transpose:
A.transpose(0,2,1)
#array([[[ 1, 4],
# [ 2, 5],
# [ 3, 6]],
# [[ 7, 10],
# [ 8, 11],
# [ 9, 12]]])
For the sake of completeness, there are is also moveaxis which replaces the deprecated rollaxis:
>>> np.rollaxis(A, 2, 1)
array([[[ 1, 4],
[ 2, 5],
[ 3, 6]],
[[ 7, 10],
[ 8, 11],
[ 9, 12]]])
>>> np.moveaxis(A, 2, 1)
array([[[ 1, 4],
[ 2, 5],
[ 3, 6]],
[[ 7, 10],
[ 8, 11],
[ 9, 12]]])
The transformation you seek:
A = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
solution = np.array([A[0].T,A[1].T])

Why does the HoughLinesP output a 3D array, instead of a 2D array?

I was working with the function (Python, Numpy, OpenCV3) over an image, and this is the sample output I have -
[[[539 340 897 538]]
[[533 340 877 538]]
[[280 460 346 410]]
[[292 462 353 411]]
[[540 343 798 492]]]
Its size is (5,1,4)
I am trying to understand what scenario will the function output something like (5,2,4) or (5,3,4). But I can't think of any and all the images I have worked with right now, it's a 3D array with the number of columns as 1.
Wouldn't just a 2D array be sufficient and perhaps more efficient?
I asked on the OpenCV Q&A and got the following response -
opencv is a c++ library, and the python wrappers are auto-generated
from some scripts, so in c++ we have:
vector lines; to hold the hough results.
now unfortunately , Vec4i is a descendant of Matx , which is actually
a 2d thing, so in python you get:
[ #one for the vector
[ #one for the 1st dim of Vec4i (1, pretty
useless, admittedly :)
[ #one for the 2nd dim of Vec4i (4 elements)
again, i think, you'll just have to live with it.
If you dont want the extra dimension and since it is 1, just use squeeze
>>> a = np.arange(5*4).reshape(5,1,4)
>>> a
array([[[ 0, 1, 2, 3]],
[[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11]],
[[12, 13, 14, 15]],
[[16, 17, 18, 19]]])
>>> a.squeeze()
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
Sometimes the extra axis comes in handy
a.swapaxes(1,2)
array([[[ 0],
[ 1],
[ 2],
[ 3]],
... Snip
[[16],
[17],
[18],
[19]]])
in light of the update and assuming the first is needed either of these return the same results assuming the extra dimension isn't needed.
>>> a[0].squeeze()
array([0, 1, 2, 3])
>>> a.squeeze()[0]
array([0, 1, 2, 3])

Resources