我正在尝试将包含正数据和负数据的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'
答案 0 :(得分:1)
我不确定我是否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
上执行计算。