简体   繁体   中英

numpy issue with concatenating arrays

I am porting some Matlab code to python and I have the following statement in Matlab:

cross([pt1,1]-[pp,0],[pt2,1]-[pp,0]);

pt1 , pt2 and pp are 2D points.

So, my corresponding python code looks as follows:

np.cross(np.c_[pt1 - pp, 1], np.c_[pt2 - pp, 1])

The points are defined as:

pt1  = np.asarray((440.0, 59.0))
pt2 = np.asarray((-2546.23, 591.03))
pp = np.asarray([563.,  456.5])

When I execute the statement with the cross product, I get the following error:

ValueError: all the input array dimensions except for the concatenation axis must match exactly

So looking at some other posts, here I thought I would try np.column_stack but I get the same error:

np.cross(np.column_stack((pt1 - pp, 1)), np.column_stack((pt2 - pp, 1)))

这可能是您要寻找的:

np.cross(np.append(pt1-pp, 1), np.append(pt2-pp, 1))

If you use np.r_ instead it works:

In [40]: np.cross(np.r_[pt1 - pp, 1], np.r_[pt2 - pp, 1])
Out[40]: array([-5.32030000e+02, -2.98623000e+03, -1.25246611e+06])

Your pt1 and pp are (2,) arrays. To add a 1 to them you need to use a 1d concatenate, np.r_ for 'row', as opposed to columns .

There are lots of ways of constructing a 3 element array:

In [43]: np.r_[pt1 - pp, 1]
Out[43]: array([-123. , -397.5,    1. ])
In [44]: np.append(pt1 - pp, 1)
Out[44]: array([-123. , -397.5,    1. ])
In [45]: np.concatenate((pt1 - pp, [1]))
Out[45]: array([-123. , -397.5,    1. ])

concatenate is the base operation. The others tweak the 1 to produce a 1d array that can be joined with the (2,) shape array to make a (3,).

Concatenate turns all of its inputs into arrays, if they aren't already: np.concatenate((pt1 - pp, np.array([1]))) .

Note that np.c_ docs say it is the equivalent of

np.r_['-1,2,0', index expression]

That initial string expression is a bit complicated. The key point is it tries to concatenate 2d arrays (whereas your pt1 is 1d).

It is like column_stack, joining n (2,1) arrays to make a (2,n)` array.

In [48]: np.c_[pt1, pt2]
Out[48]: 
array([[  440.  , -2546.23],
       [   59.  ,   591.03]])
In [50]: np.column_stack((pt1, pt2))
Out[50]: 
array([[  440.  , -2546.23],
       [   59.  ,   591.03]])

In MATLAB everything has at least 2 dimensions, and because it is Fortran based, the outer dimensions are last. So in a sense its most natural 'vector' shape is nx 1, a column matrix. numpy is built on Python, with a natural interface to its scalars and nested lists. Order is c based; the initial dimensions are outer most. So numpy code can have true scalars (Python numbers without shape or size), or arrays with 0 or more dimensions. A 'vector' most naturally has shape (n,) (a 1 element tuple). It can easily be reshaped to (1,n) or (n,1) if needed.

If you want a (3,1) array (instead of (3,) shaped), you'd need to use some sort of 'vertical' concatenation, joining a (2,1) array with a (1,1):

In [51]: np.r_['0,2,0', pt1-pp, 1]
Out[51]: 
array([[-123. ],
       [-397.5],
       [   1. ]])
In [53]: np.vstack([(pt1-pp)[:,None], 1])
Out[53]: 
array([[-123. ],
       [-397.5],
       [   1. ]])

(But np.cross wants (n,3) or (3,) arrays, not (3,1)!)

In [58]: np.cross(np.r_['0,2,0', pt1-pp, 1], np.r_['0,2,0', pt2-pp, 1])
...
ValueError: incompatible dimensions for cross product
(dimension must be 2 or 3)

To get around this specify an axis:

In [59]: np.cross(np.r_['0,2,0', pt1-pp, 1], np.r_['0,2,0', pt2-pp, 1], axis=0)
Out[59]: 
array([[-5.32030000e+02],
       [-2.98623000e+03],
       [-1.25246611e+06]])

Study np.cross if you want an example of manipulating dimensions. In this axis=0 case it transposes the arrays so they are (1,3) and then does the calculation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM