-2

Let's say I have this calculation to do:

The law I am trying to apply to calculate xd and yd

What is the best way to do it in Python? I come from a Matlab background and Matrices in Matlab are so easy to handle. I have tried with numpy but it gives me this error message:

ValueError: setting an array element with a sequence. 

Here is a snippet of my code:

for i in Xh:
    for u in Yh:    
        E= (np.array([(C,D),(E,F)]) * np.array([(i),(u)]) ) + np.array([Cx,Cy])

Please note that Xh and Yh are lists already calculated, this is why I am using the for loops (I know I can make it faster with list comprehensions).

Edit: This is a good solution that I got from this topic, and that works perfectly. For anyone who is facing the same problem, it could help.

a = np.matrix([[1,2],[3,4]])
v1 = np.matrix([[0],[1]])
v2 = np.matrix([[1],[1]])

res = np.dot(a,v1)+v2 # python version <= 3.5
res = a@v1+v2 # python version > 3.5 with the new dot operator @
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Mourad Over Flow
  • 191
  • 1
  • 5
  • 16
  • Can you provide a [MCVE](http://stackoverflow.com/help/mcve)? – Nuageux Jun 29 '17 at 13:24
  • Use [`numpy.dot`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html) for matrix-vector multiplications. The `*` operator performs an element-wise multiplication via [broadcasting](https://docs.scipy.org/doc/numpy-1.12.0/user/basics.broadcasting.html). – a_guest Jun 29 '17 at 13:25
  • `()` creates a sequence, you should be using `[]` around your array elements. Also if you're trying to do matrix multiplication use `mat_name.dot(vector_name)`. At a quick glance `E = np.array([[C,D],[E,F]]).dot(np.array([i,u])) + np.array([Cx,Cy])` should be sufficient. – alkasm Jun 29 '17 at 13:26

3 Answers3

2

If you want to have an experience close to matlab it is possible to use np.matrix instead of np.array. Your mathematical example would then be, e.g.

a = np.matrix([[1,2],[3,4]])
v1 = np.matrix([[0],[1]])
v2 = np.matrix([[1],[1]])

res = a*v1+v2

This is however not recommended by the numpy docs as pointed out in the comments. The way to do it with arrays is very similar. Here * is however the element-wise multiplication (.* in matlab). The matrix multiplication can then be done with:

a = np.matrix([[1,2],[3,4]])
v1 = np.matrix([[0],[1]])
v2 = np.matrix([[1],[1]])

res = np.dot(a,v1)+v2 # python version <= 3.5
res = a@v1+v2 # python version > 3.5 with the new dot operator @
Jannick
  • 1,036
  • 7
  • 16
  • 2
    True, but I think you should edit to include the proper way to do this with arrays too, since they're far more common and OP is likely to come across them in the future. – alkasm Jun 29 '17 at 13:28
  • [Use arrays](https://docs.scipy.org/doc/numpy-dev/user/numpy-for-matlab-users.html#array-or-matrix-which-should-i-use), not matrices! – Mark Dickinson Jun 29 '17 at 13:58
1

I found two problems in your code:

  1. You use round instead of squared brackets - you have to feed numpy's 2d arrays with a list of lists [[a0, a1],[a2, a3]]. This is where your ValueError comes from.
  2. You use m1 * m2, which is the element-wise dot-product, but you should be using the matrix dot product np.dot(m1,m2) or its equivalent form m1.dot(m2).

Corrected:

for i in Xh:
    for u in Yh:
        E = np.dot(np.array([[C, D], [E, F]]), np.array([[i], [u]])) + np.array([[Cx], [Cy]])
Manu CJ
  • 2,629
  • 1
  • 18
  • 29
1

You can make use of np.meshgrid to produce all combinations of Xh and Yh, and then np.einsum and broadcasting here to vectorize (read: speed up by a factor of 100x) the entire operation in one line:

import numpy as np

C, D, E, F = 1, 2, 3, 4
Cx, Cy = 1, 2
Xh = [1, 2, 3]
Yh = [4, 5, 6]

XhYh = np.array(np.meshgrid(Xh, Yh)).T.reshape(-1, 2)
M = np.array([[C, D], [E, F]])
V = np.array([Cx, Cy])

E = np.einsum('mk,fk->fm', M, XhYh) + V

Speed comparison for 100000 XhYh entries:

%timeit np.einsum('mk,fk->fm', M, XhYh) + V
# 209 µs ± 2.51 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.array([M.dot(np.array([x, y])) + V for x in Xh for y in Yh])
# 32.5 ms ± 608 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
  • What would be the benefits of `np.einsum()` over `ndarray.dot()`with or `*` with `np.matrix` variables? – alkasm Jun 29 '17 at 13:33
  • While for large matrices `.dot()` is faster than `einsum('mk,k->m')`, `einsum()` and using broadcasting in `... + V` are faster than a Python `for` loop. – Nils Werner Jun 29 '17 at 13:33