Панды: Как мне объединить значения двух столбцов данных, которые совпадают в пределах некоторого допуска? - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь сопоставить два набора строк в pandas фреймах данных, содержащих положительные и отрицательные данные, с точностью до некоторых пользовательских tolerance, например (изначально):

timestamp value has_a_matching_minus should_match_tolerance_equals_ten
01  36.00    False False
02  68.00    False False
03  131.00   False False
04  94.00    False True
05  -1000.00 False False
06  100.00   False True
07  540.00   False False
08  -100.00  False False
09  54.00    False False

(создать с помощью:

 df = pd.DataFrame({'timestamp': range(9), 'value': [36, 68, 131, 94, -1000, 100, 540, -100, 54]})

plusses может иметь или не иметь одно (или более) совпадение в minuses. Если плюс соответствует совпадению в пределах допуска, соответствующая строка plusses должна иметьего столбец 'has_a_matching_minus' установлен на True (в противном случае он остается False).

Я знаю, что могу использовать df.between(low,high), но он принимает только low и high в качестве скаляров ине столбцы серии / датафрейма.

Как можно избежать следующего (медленного!) for зацикливания between? Стоит ли использовать merge и т. д.?

import numpy as np
import pandas as pd

minuses=data[data['value']<0.0]
plusses=data[data['value']>0.0]

tolerance = 10.0
match_queries      = np.abs(minusses)
match_queries_high = match_queries + tolerance
match_queries_low  = match_queries - tolerance

plusses['has_a_matching_minus'] = False
for (l, h) in zip(match_queries_low, match_queries_high):
    in_range = plusses['value'].between(l,h).astype(np.bool)
    plusses['has_a_matching_minus'] = plusses['has_a_matching_minus'] | in_range

assert(plusses['has_a_matching_minus']==plusses['should_match_tolerance_equals_ten'].all()), 'The acid test'

1 Ответ

0 голосов
/ 18 мая 2018

Я не уверен, что получил подробные данные вопроса на 100%, но, вероятно, следующее может показать, как подойти к нему.

Предположим, вы начинаете с

df = pd.DataFrame({'timestamp': range(9), 'value': [36, 68, 131, 94, -1000, 100, 540, -100, 54]})

Используйтестолбец-пустышка для выполнения самостоятельного внешнего соединения:

df['dummy'] = 1
merged = pd.merge(df, df, on='dummy', how='outer')

Теперь рассчитайте для каждой временной отметки, существует ли другое отрицательное значение, самое большее отличающееся от него, в абсолютном значении самое большее на расстоянии 10:

merged['has_a_matching_minus'] = (merged.timestamp_x != merged.timestamp_y) & (merged.value_y < 0) & ((merged.value_x.abs() - merged.value_y.abs()).abs() < 10)

>>> merged.has_a_matching_minus.astype(int).groupby(merged.timestamp_x).max().astype(bool).to_frame()


has_a_matching_minus
timestamp_x 
0   False
1   False
2   False
3   True
4   False
5   True
6   False
7   False
8   False

Вы можете легко merge это в оригинальную рамку.Если вам нужно несколько столбцов, выполните их вычисления для merged аналогично.

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