Могу ли я использовать лямбда, map, apply или applymap для заполнения кадра данных? - PullRequest
3 голосов
/ 12 марта 2019

Это упрощенная версия моих данных. У меня есть массив данных с координатами и пустой кадр данных, который должен быть заполнен расстоянием каждой пары, используя предоставленную функцию.

Какой самый быстрый способ заполнить этот фрейм данных? Насколько это возможно, я хочу держаться подальше от вложенных циклов (медленно!). Могу ли я использовать apply или applymap? Вы можете изменить функцию или другие части соответственно. Спасибо.

import pandas as pd

def get_distance(point1, point2):
    """Gets the coordinates of two points as two lists, and outputs their distance"""
    return (((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2 + (point1[2] - point2[2]) ** 2) ** 0.5)

#Dataframe of coordinates.    
df = pd.DataFrame({"No.": [25, 36, 70, 95, 112, 101, 121, 201], "x": [1,2,3,4,2,3,4,5], "y": [2,3,4,5,3,4,5,6], "z": [3,4,5,6,4,5,6,7]})
df.set_index("No.", inplace = True)

#Dataframe to be filled with each pair distance.
df_dist = pd.DataFrame({'target': [112, 101, 121, 201]}, columns=["target", 25, 36, 70, 95])
df_dist.set_index("target", inplace = True)

Ответы [ 2 ]

0 голосов
/ 12 марта 2019

AFAIK, нет явного преимущества в скорости от лямбды по сравнению с циклом for - и очень сложно написать двойную лямбду, обычно зарезервированную для простых операций со строками.

Однако с помощью некоторой разработки мы можем уменьшитьнаш код в несколько простых и понятных строк:

import numpy as np

get = lambda i: df.loc[i,:].values
dist = lambda i, j: np.sqrt(sum((get(i) - get(j))**2))
# Fills your df_dist
for i in df_dist.columns:
    for j in df_dist.index:
        df_dist.loc[j,i] = dist(i, j)

В результате df_dist:

              25        36        70        95
target                                        
112     1.732051  0.000000  1.732051  3.464102
101     3.464102  1.732051  0.000000  1.732051
121     5.196152  3.464102  1.732051  0.000000
201     6.928203  5.196152  3.464102  1.732051
0 голосов
/ 12 марта 2019

Если вы не хотите использовать для циклов, вы можете вычислить расстояния между всеми возможными парами следующим образом.

Сначала вам нужно сделать декартово произведение df для себя, чтобыиметь все возможные пары точек.

i, j = np.where(1 - np.eye(len(df)))
df=df.iloc[i].reset_index(drop=True).join(
    df.iloc[j].reset_index(drop=True), rsuffix='_2')

Где i и j - логические индексы верхнего и нижнего треугольников квадратной матрицы размера len(df).После того, как вы это сделали, вам просто нужно применить вашу функцию расстояния

df['distance'] = get_distance([df['x'],df['y'],df['z']], [df['x_2'],df['y_2'],df['z_2']])
df.head()

No. x   y   z   No._2   x_2 y_2 z_2 distance
0   25  1   2   3   36  2   3   4   1.732051
1   25  1   2   3   70  3   4   5   3.464102
2   25  1   2   3   95  4   5   6   5.196152
3   25  1   2   3   112 2   3   4   1.732051
4   25  1   2   3   101 3   4   5   3.464102

Если вы хотите вычислить только точки из df_dist, вы можете соответственно изменить матрицу 1 - np.eye(len(df)).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...