我有以下示例数据集:
In [222]: df
Out[222]:
ci_low circ_time_angle ci_high
0 30 30 30
1 10 0 20
2 -188 143 207
3 -188 4 207
4 -188 8 207
5 -188 14 207
6 -188 327 207
7 242 57 474
8 242 283 474
9 242 4 474
10 -190 200 -1
11 -90 300 0
12 -25 15 60
13 -30 349 350
14 420 30 600
15 -100 23 719
16 -100 23 259
17 -350 5 -10
18 -350 11 -10
其中:
ci_low
-是循环置信区间(CI)的下限circ_time_angle
-我想检查它是否属于CI的角度ci_high
-是循环置信区间(CI)的上限约束:
0 <= circ_time_angle <= 360
ci_high >= ci_low
ci_low
和ci_high
不一定属于[0, 360]
(请参见示例数据集中的[2-18]
行)。 问题:检查角度circ_time_angle
是否落入圆形置信区间:[ci_low, ci_high]
的优雅方法是什么?
还是我需要单独检查所有边缘情况?
所需/结果数据集:
In [224]: res
Out[224]:
ci_low circ_time_angle ci_high falls_into_CI
0 30 30 30 True
1 10 0 20 False
2 -188 143 207 True
3 -188 4 207 True
4 -188 8 207 True
5 -188 14 207 True
6 -188 327 207 True
7 242 57 474 True
8 242 283 474 True
9 242 4 474 True
10 -190 200 -1 True
11 -90 300 0 True
12 -25 15 60 True
13 -30 349 350 True
14 420 30 600 False
15 -100 23 719 True
16 -100 23 259 True
17 -350 5 -10 False
18 -350 11 -10 True
我还尝试将CI边界转换为[0, 360]
和[-180, 180]
,但这仍然没有帮助我找到一个优雅的公式。
样本数据集设置:
data = {
'ci_low': [30,
10,
-188,
-188,
-188,
-188,
-188,
242,
242,
242,
-190,
-90,
-25,
-30,
420,
-100,
-100,
-350,
-350],
'circ_time_angle': [30,
0,
143,
4,
8,
14,
327,
57,
283,
4,
200,
300,
15,
349,
30,
23,
23,
5,
11],
'ci_high': [30,
20,
207,
207,
207,
207,
207,
474,
474,
474,
-1,
0,
60,
350,
600,
719,
259,
-10,
-10]}
df = pd.DataFrame(data)
答案 0 :(得分:1)
目前,我提出了以下想法:
True
['ci_low', 'circ_time_angle', 'ci_high']
的方式旋转所有角度(列:ci_low == 0
)并比较旋转 {{1} } 代码:
circ_time_angle % 360 <= ci_high % 360
检查:
def angle_falls_into_interval(angle, lower, upper, high=360):
# rotate ALL angles in the way,
# so that the lower angle = 0 degrees / radians.
lower = np.asarray(lower)
angle = np.asarray(angle) - lower
upper = np.asarray(upper) - lower
lower -= lower
return np.where(upper-lower >= high,
True,
(angle % high) <= (upper % high))
答案 1 :(得分:1)
我会尝试将[0:360)范围内的ci_low归一化,并将ci_high
更改为相同的值。然后,如果circ_time_angle
之下的ci_low
加上360。
此后,位于CI间隔内的条件仅为circ_time_angle<ci_high
。
我使用辅助数据框来防止df
中的任何变化:
limits = df[['ci_low', 'ci_high']].copy() # copy ci_low and ci_high
limits.columns=['low', 'high'] # rename to have shorter names
# ensure ci_low is in the [0-360) range
delta = (limits['low'] // 360) * 360
limits['low'] -= delta
limits['high'] -= delta
limits['circ'] = df['circ_time_angle'] # copy circ_time_angle
# add 360 to circ_time_angle if it is below low
limits.loc[limits.circ < limits.low, 'circ'] += 360
df['falls_into_CI'] = limits['circ']<=limits['high']
它给出了预期的结果:
ci_low circ_time_angle ci_high falls_into_CI
0 30 30 30 True
1 10 0 20 False
2 -188 143 207 True
3 -188 4 207 True
4 -188 8 207 True
5 -188 14 207 True
6 -188 327 207 True
7 242 57 474 True
8 242 283 474 True
9 242 4 474 True
10 -190 200 -1 True
11 -90 300 0 True
12 -25 15 60 True
13 -30 349 350 True
14 420 30 600 False
15 -100 23 719 True
16 -100 23 259 True
17 -350 5 -10 False
18 -350 11 -10 True
如果一切都矢量化了,这是个好主意。