优雅(最有效)的方法来检查角度是否落入圆形置信区间

时间:2019-06-26 10:21:42

标签: python pandas numpy math scipy

我有以下示例数据集:

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_lowci_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)

2 个答案:

答案 0 :(得分:1)

目前,我提出了以下想法:

  1. 检查那些涵盖360+度的CI间隔,并将相应行的结果设置为True
  2. 对于所有其他行,以['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

如果一切都矢量化了,这是个好主意。