2

I am trying to calculate a resultant acceleration from x, y, z accelerations. I have written a function that does this when manually inputting the x,y,z coordinates.

def Euclidean_norm(x,y,z):
    total = (x ** 2) + (y ** 2) + (z ** 2)
    resultant = math.sqrt(total)
    return resultant

My problem is that I want to use this function to iterate over 3 lists, and produce a new list with only the resultant acceleration.

x_list = [(9.6,), (4.9,), (8.7,), (9.....]
y_list = [(0.6,), (2.6,), (4.6,), (2.....]
z_list = [(5.2,), (7.2,), (5.8,), (7.....]

I have tried to use the map function

print(map(Euclidean_norm(a,b,c)))

However this gave an error

TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'

Part of the problem is that the values for x, y and z I get from the database come out as tuples instead of plain numbers.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • please don't post images of code. Include the code as text and format it properly. – Mad Physicist Apr 26 '18 at 14:25
  • Sorry, its my first question. I will add code as text from here onwards. – Romesh Tirimanna Apr 26 '18 at 14:27
  • Please fix what you have now. Also, provide the results of any printouts in the question. Your verbal description does not match what is actually happening, which is why you aren't finding the right solution. – Mad Physicist Apr 26 '18 at 14:31
  • Thanks, I tried to add the whole code to my question, but this wasn't possible for some reason. This is useful information for my next question. I have tried to remove the picture as well. – Romesh Tirimanna Apr 26 '18 at 14:42
  • Please try one more time. I would like to post an answer, but your question is not complete and you really should edit it. The thing is that SO is a site for any user to be able to get help by reading the Q&A. It is not a personal helpdesk. It could make a difference to someone in the future if you fixed your question. – Mad Physicist Apr 26 '18 at 16:24

2 Answers2

3

Use a list-comprehension with zip():

[Euclidean_norm(*x,*y,*z) for x,y,z in zip(x_list, y_list, z_list)]

Oh, and you shouldn't capitalise functions as capitalised names are reserved for classes.


Just a little explanation...

The zip() function takes any number of iterables and "zips" them together to give tuples made from the corresponding indexes. It is a really useful function for iterating over related lists like the ones here.

To demonstrate it a bit clearer:

>>> a = [1, 2, 3]
>>> b = [2, 4, 6]
>>> list(zip(a, b))
[(1, 2), (2, 4), (3, 6)]
>>> for i, j in zip(a, b):
...     print(i, j)
... 
1 2
2 4
3 6
Joe Iddon
  • 20,101
  • 7
  • 33
  • 54
  • Thank you for your reply. I have tried the code that you suggested, but this gives the error "unsupported operand type(s) for ** or pow(): 'tuple' and 'int'". – Romesh Tirimanna Apr 26 '18 at 13:54
  • are you sure you have copied the code exactly? it worked when I tested... from that error it sounds like you aren't unpacking into the `x, y, z` variables properly... – Joe Iddon Apr 26 '18 at 13:56
  • list(zip(x_list, y_list, z_list)) worked and produced a new list with the x, y and z coordinates. However when doing [Euclidean_norm(x,y,z) for x,y,z in zip(x_list, y_list, z_list)] it still gives the error. Im not sure what you mean by unpacking? I am quite new to python. But thanks for the help. – Romesh Tirimanna Apr 26 '18 at 14:16
  • I have tried to add an image to my question so that you can see my code. Just some more background, the lists of the x,y,z accelerations are being taken from an SQLite database. – Romesh Tirimanna Apr 26 '18 at 14:19
  • It is confusing since the code you posted looks fine... what it the result of that `print(a)` call? – Joe Iddon Apr 26 '18 at 14:27
  • @RomeshTirimanna. The code in your image has a list of tuples, but your question is about a list of integers. – Mad Physicist Apr 26 '18 at 14:28
  • The print(a) shows a list of all the x axis acceleration values in my SQLite table. – Romesh Tirimanna Apr 26 '18 at 14:29
  • @JoeIddon. The get from db pretty clearly gets some sort of sequence, probably a tuple, for each element. – Mad Physicist Apr 26 '18 at 14:30
  • @MadPhysicist Yes, I agree. Romesh your functions which generate the `x_list`, `y_list` and `z_list`, do not return lists like those you have in the question. Please look more carefully at what these functions return from the SQLite database as they are **not** lists of floats as you have in the question. – Joe Iddon Apr 26 '18 at 14:33
  • @JoeIddon thank you, I will try to see what data type these functions are returning and go from there. maybe if I can change them to lists, your suggestion will work. Again thanks for helping and your patience. – Romesh Tirimanna Apr 26 '18 at 14:43
  • @JoeIddon I am a bit confused because when I try print(type(a)) it returns . Do you have any recommendations on what to check next? – Romesh Tirimanna Apr 26 '18 at 15:03
  • 1
    @RomeshTirimanna what about `typw(a[0])`? Just because it's a list doesn't mean it contains what you want. – Mad Physicist Apr 26 '18 at 15:08
  • @MadPhysicist type(a[0]) gives . So as you said there is something else going on here. Does this mean that it's a list of tuples? – Romesh Tirimanna Apr 26 '18 at 15:25
  • Yes, it is a list of tuples! – Joe Iddon Apr 26 '18 at 15:26
  • I just checked, and the x_list [] returned looks like this: [(-4,), (-4,), (-4,), (-4,),... – Romesh Tirimanna Apr 26 '18 at 15:27
  • Are they all `-4`s or do some change... are these the values just all in tuples – Joe Iddon Apr 26 '18 at 15:29
  • @JoeIddon no, although the first few are -4, they do change from there onwards. However, they do all seem to be tuples in this format (x,), with a number and a space. – Romesh Tirimanna Apr 26 '18 at 15:34
  • Okay, I have updated the answer, hopefully it should work now! – Joe Iddon Apr 26 '18 at 15:40
1

@JoeIddon's excellent answer shows one of a handful of possible solutions. The main problem there is that your tuples are being unpacked when you call the final function. You may want to consider unpacking them immediately when they are returned from the database, since your code seems to expect that:

x_list = [x[0] for x in x_list]

A slightly faster version that is only a good idea if you have very large lists would be

from operator import itemgetter
g = itemgetter(0)
x_list = [g(x) for x in x_list]

Once the tuples are unpacked, the zipped solution reverts back to the original proposal:

resultant = [Euclidean_norm(x, y, z) for x, y, z in zip(x_list, y_list, z_list]

or alternatively:

resultant = [Euclidean_norm(*accel) for accel in zip(x_list, y_list, z_list]

Another option is to stick with map, like you tried before. The problem you had is that the syntax print(map(Euclidean_norm(a,b,c))) does not use map properly. The expression Euclidean_norm(a,b,c) actually calls Euclidean_norm right there and then with lists as arguments, instead of passing the function object to map. You would want to do something like map(Euclidean_norm, a, b, c):

resultant = list(map(Euclidean_norm, x_list, y_list, z_list))

You need to apply list to map because map returns a generator that will not be evaluated until you need the elements.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264