How to calculate distance from points in lists?

2019-08-29 06:29发布

问题:

I have two group of lists, A and O. Both of them have points from x,y z coordinate. I want to calculate the distance between points from A and B. I used a for loop, but it only give me one result. It should give me 8 numbers from the results. I'm very appreciate that someone can have a look. It's the last step in my project.

Ax = [-232.34, -233.1, -232.44, -233.02, -232.47, -232.17, -232.6, -232.29, -231.65] 
Ay = [-48.48, -49.48, -50.81, -51.42, -51.95, -52.25, -52.83, -53.63, -53.24] 
Az = [-260.77, -253.6, -250.25, -248.88, -248.06, -247.59, -245.82, -243.98, -243.76]
Ox = [-302.07, -302.13, -303.13, -302.69, -303.03, -302.55, -302.6, -302.46, -302.59] 
Oy = [-1.73, -3.37, -4.92, -4.85, -5.61, -5.2, -5.91, -6.41, -7.4] 
Oz = [-280.1, -273.02, -269.74, -268.32, -267.45, -267.22, -266.01, -264.79, -264.96]
distance = []
for xa in A1:
    for ya in A2:
        for za in A3:
            for x1 in o1:
                for y1 in o2:
                    for z1 in o3:
                        distance += distance
                        distance = (((xa-x1)**2)+((ya-y1)**2)+((za-z1)**2))**(1/2)  
print(distance)

回答1:

Other people have provided fixes to your immediate problem. I would also recommend that you start using numpy and avoid all of those for loops. Numpy provides ways to vectorize your code, basically offload all of the looping that needs to be done to very efficient C++ implementations. For instance, you can replace your whole nested for-loop thing with the following vectorized implementation:

import numpy as np

# Convert your arrays to numpy arrays
Ax = np.asarray(Ax)
Ay = np.asarray(Ay)
Az = np.asarray(Az)
Ox = np.asarray(Ox)
Oy = np.asarray(Oy)
Oz = np.asarray(Oz)
# Find the distance in a single, vectorized operation
np.sqrt(np.sum(((Ax-Ox)**2, (Ay-Oy)**2, (Az-Oz)**2), axis=0))


回答2:

Your first issue is this:

distance = (((xa-x1)**2)+((ya-y1)**2)+((za-z1)**2))**(1/2)

This despite you defining distance as a list. You're replacing a list of values with a single value. What you want is

distance.append((((xa-x1)**2)+((ya-y1)**2)+((za-z1)**2))**(1/2))

which will add this value to the end of the list.

Second thing: your workflow could be improved. Instead of using that many for loops, try doing this: You know that the lengths of A1, A2, A3, o1, o2, and o3 are the same length, so:

distance = []
for i in range(len(A1)): # will run 8 times because the length of A1 is 8
    xa, ya, za = A1[i], A2[i], A3[i] # these values correspond to each other
    xb, yb, zb = o1[i], o2[i], o3[i] # all are in the same position in their respective list
    distance.append((((xa-x1)**2)+((ya-y1)**2)+((za-z1)**2))**(1/2))
print distance


回答3:

You need to be appending to distance not assigning it. You should be doing something like this inside of your for loops: distance.append((((xa-x1)**2)+((ya-y1)**2)+((za-z1)**2))**(1/2))



回答4:

By nesting all those loops, you're going to be executing each "subloop" every iteration of the "parent loop", and so on, resulting in far more loops than necessary and some mixed up data. As other answers have mentioned, you're also reassigning distance to the value of the last calulation of the inner-most loop, every pass.

You can do all of this a lot more efficiently by zipping the data.

distance = []
for ptA, ptB in zip(zip(Ax, Ay, Az), zip(Ox, Oy, Oz)):
    distance.append(pow(sum(pow(a - b, 2) for a, b in zip(ptA, ptB)), 0.5))


回答5:

Your nested loops are not merely inefficient, but incorrect. You are going through every combination of x, y, and z values for both sets of points.

Here's a list comprehension to accomplish the task:

distance = [((xa-x1)**2 + (ya-y1)**2 + (za-z1)**2)**(0.5)
            for (xa, ya, za, x1, y1, z1) in zip(Ax, Ay, Az, Ox, Oy, Oz)]

The zip call produces groups of the corresponding coordinate values. These are then unpacked into individual values for a given pair of points. Then the distances is calculated and added to the resulting list. Here is the result:

[86.14803712215387, 85.25496701072612, 86.50334270997855, 86.02666679582558, 86.61455593605497, 86.90445212991106, 86.65519315078585, 87.10116761559514, 87.08173861378742]

Note that the (1/2) in your formula works for Python 3, but not for Python 2. I've use 0.5, which will work for both. Using math.sqrt() might be an even better idea.