Сравнение пары значений в датафрейме, условие для создание нового столбца
Есть датафрейм с координатами:
df = pd.DataFrame([[13.6,9.1], [9,6.3], [9.3,6.1], [13.7,9.2], [1.5,7.5]], columns=['x','y'])
Необходимо сделать новый столбец с меткой по условию: если есть точка которая расположена близко, то есть разница координат для x и y лежит в заданном диапазоне, то 1 если нет такой точки то 0. Я пытаюсь сделать хотя бы для одной точки:
point = df.head(1).copy()
[1 if (-0.2<(point.x-df.x[i])) & ((point.x-df.x[i])<0) &
(-0.2<(point.y-df.y[i])) & ((point.y-df.y[i])<0.2) else 0 for i in df.index]
Но выдает ошибку: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Если Полностью: нужно перебрать все пары значений x\y, сравнить их со всеми x\y из этого же датафрейма и если разница хотя бы для одной пары координат лежит в заданоом диапазоне, то вернуть 1 если таких совпадений нет, то 0
UPDATE: Написал вот такую функцию, которая возвращает списки для каждой пары значений:
df['new_col'] = df.apply(lambda a: [1 if (-0.2 < (a.x-df.x[i]) < 0) and (-0.2 < (a.y-df.y[i]) < 0.2) else 0 for i in df.index], axis=1)
Теперь встает вопрос как избавиться от лишних значений, можно просто обработать списки и достать наибольшее значение, но хочется переписать функцию, возможно без применения lambda, чтобы она возвращала не список, а только 1 если есть совпадения по условиям и 0 если нет.
Ответы (1 шт):
Наверняка можно проще, но можно в общем как-то так:
from sklearn.neighbors import DistanceMetric
import numpy as np
dist = DistanceMetric.get_metric('euclidean')
d = dist.pairwise(df)
# это хитрость чтобы нули (сравнение с собой) не были минимумом
d += np.eye(d.shape[0]) * d.max() * 2
df['dist'] = d.min(axis=1)
df
Вывод:
| index | x | y | dist |
|---|---|---|---|
| 0 | 13.6 | 9.1 | 0.141421356237309 |
| 1 | 9.0 | 6.3 | 0.3605551275463996 |
| 2 | 9.3 | 6.1 | 0.3605551275463996 |
| 3 | 13.7 | 9.2 | 0.141421356237309 |
| 4 | 1.5 | 7.5 | 7.595393340703297 |
Но тут я взял Евклидово расстояние, т.е. корень суммы квадратов разностей по координатам. Если вам нужно просто сравнить максимум разностей координат по модулю (судя по тому, что вы пытались сделать), то это будет метрика Чебышева DistanceMetric.get_metric(“chebyshev”) и результат будет такой:
| index | x | y | dist |
|---|---|---|---|
| 0 | 13.6 | 9.1 | 0.09999999999999964 |
| 1 | 9.0 | 6.3 | 0.3000000000000007 |
| 2 | 9.3 | 6.1 | 0.3000000000000007 |
| 3 | 13.7 | 9.2 | 0.09999999999999964 |
| 4 | 1.5 | 7.5 | 7.5 |
А дальше просто сравниваете этот dist с вашим пороговым значением - и получаете нужный вам признак.
P.S. Код к вопросу из комментария:
df['new_col'] = df.apply(lambda a: int(any([1 if (-0.2 < (a.x-df.x[i]) < 0) and (-0.2 < (a.y-df.y[i]) < 0.2) else 0 for i in df.index])), axis=1)
