Как проверить, между каким пороговым уровнем находится значение?

#python-3.x #pandas #logic

#python-3.x #pandas #Логические

Вопрос:

У меня есть фрейм данных, содержащий столбцы, выглядящие следующим образом (имеющие 1400 уникальных contextID записей и 28 разных IndicatorID записей):

 ContextID   IndicatorID threshold_values    AlarmLevel  actual_values
7289972        204511   -6.10904                 -1         0
7289972        204511   -12.1848                 -2         0
7289972        204511   -18.2606                 -3         0
7289972        204511   18.19404                  1         0
7289972        204511   24.2698                   2         0
7289972        204511   30.34557                  3         0
7289972        204512   89.94568                  1        64.114
7289972        204512   104.2932                  2        64.114
7289972        204512   118.6407                  3        64.114
7289972        204512   32.55574                 -1        64.114
7289972        204512   18.20825                 -2        64.114
7289972        204512   3.860765                 -3        64.114
7289998        204511   -6.10904                 -1           1
7289998        204511   -12.1848                 -2           1
7289998        204511   -18.2606                 -3           1
7289998        204511   18.19404                  1           1
7289998        204511   24.2698                   2           1
7289998        204511   30.34557                  3           1
7289998        204512   89.94568                  1        64.111
7289998        204512   104.2932                  2        64.111
7289998        204512   118.6407                  3        64.111
7289998        204512   32.55574                 -1        64.111
7289998        204512   18.20825                 -2        64.111
7289998        204512   3.860765                 -3        64.111
  

actual_values Столбец — это реальное значение, считываемое датчиком машины. threshold_values Столбцы содержат различные пороговые значения, определенные для различных индикаторов (в IndicatorID столбце), в зависимости от которых будет подан сигнал тревоги, если значение превысит определенный предел.

Пример: Если значение в actual_values лежит между threshold_values значениями, определенными для уровня тревоги -1 и 1, продукт не является дефектным. Но, если значение находится между -1 и -2, должен быть подан сигнал тревоги, равный -1 (поскольку оно превысило порог, определенный для -1), а если значение находится между 1 и 2, должен быть подан сигнал тревоги, равный 1, и так далее. В конце концов, для ContextID должен быть присвоен самый большой уровень тревоги, то есть, если один индикатор поднял тревогу 1, а второй индикатор поднял тревогу -2, уровень тревоги -2 должен считаться большим и присваиваться ему в качестве окончательного сигнала ContextID (предпочтительно в новом столбце).

Я хотел получить некоторую помощь в реализации этой концепции. Я хотел бы знать, можно ли закодировать такую реализацию.

Я пытаюсь реализовать это, используя 2 разных for цикла, один для всех ContextID s и другой для IndicatorID s, но почему-то мне не удается придумать логику, которая может решить эту задачу.

Я был бы благодарен за помощь и указания.

Спасибо

Редактировать 1:

Пример:

 ContextID   IndicatorID threshold_values    AlarmLevel  actual_values   thresh_high alarm_high  insideThresh
7291899 204515  0.708226    -3  0.949486    0.742542    -2  FALSE
7291899 204515  0.742542    -2  0.949486    0.76        -1  FALSE
7291899 204515  0.76        -1  0.949486    0.914122     1  FALSE
7291899 204515  0.914122    1   0.949486    0.948438     2  FALSE
7291899 204515  0.948438    2   0.949486    0.982754     3  TRUE
7291899 204515  0.982754    3   0.949486    610.9839    -3  FALSE
  

thresh_value Значение 610.9839 принадлежит другому IndicatorID (204516), но это значение используется для вычисления уровня тревоги IndicatorID (204515)

Ответ №1:

Уверен, что есть способ сделать это. Возможно, способы получше приведенного ниже, но это сработает.

Инициализировать данные:

 import pandas as pd
import numpy as np

thresh = [-6.10904,
-12.1848,
-18.2606,
18.19404,
24.2698,
30.34557,
89.94568,
104.2932,
118.6407,
32.55574,
18.20825,
3.860765]

df = pd.DataFrame({'ContextID':[1]*12 [2]*12,
                   'IndicatorID':[5]*6 [6]*6 [7]*6 [8]*6,
                   'threshold_values':thresh*2,
                   'AlarmLevel':[-1, -2, -3, 1, 2, 3, 3, 2, 1, -1, -2, -3]*2,
                   'actual_values':[-17]*6 [64.114]*6 [26]*6 [64.111]*6})
  

Я упростил ContextID и IndicatorID, я также ввел некоторые поддельные значения для actual_values, потому что все ваши значения находятся в правильном диапазоне. Мы хотим посмотреть, что произойдет, когда они выйдут за пределы надлежащего диапазона.

 df = df.sort_values(['ContextID', 'IndicatorID', 'AlarmLevel'])
df['thresh_high'] = df.groupby(['ContextID', 'IndicatorID'])['threshold_values'].shift(-1)
df['alarm_high'] = df.groupby(['ContextID', 'IndicatorID'])['AlarmLevel'].shift(-1)
df['thresh_high'] = df.thresh_high.fillna(np.Inf)
df['alarm_high'] = df.alarm_high.fillna(4)
df['insideThresh'] = (df.actual_values < df.thresh_high) amp; (df.actual_values > df.threshold_values)
  

Мы сортируем фрейм данных, а затем создаем thresh_high и alarm_high , которые являются сдвинутыми версиями threshold_values и AlarmLevel

Затем мы создаем столбец, который просто показывает, находится ли фактическое значение между пороговыми значениями.

 alarms = df.loc[df.insideThresh == True] 
            .groupby(['ContextID', 'IndicatorID', 'insideThresh'])['AlarmLevel'] 
            .apply(lambda x: x.min() 1 if x.min() < 0 else x.min()
  

)

Наконец, мы фильтруем фрейм данных только для тех случаев, когда actual_values значение находилось в пороговых значениях, а затем группируем по ContextID, IndicatorID и insideThresh (это последнее на самом деле не нужно). Мы берем уровень тревоги и применяем пользовательскую функцию, сообщающую ему, что если минимум уровня тревоги, с которого он был нарушен, отрицательный, увеличьте уровень на 1, в противном случае увеличьте минимальный.

Комментарии:

1. Конечно, изменение порога и значения уровня тревоги работает. Интересно, почему я не подумал об этом простом решении. Спасибо, Мэтт, что помог мне 🙂

2. Привет, @Matt, у меня был небольшой запрос. Не могли бы вы объяснить, что вы имеете в виду, когда говорите, если минимум аварийного уровня, с которого он был нарушен, отрицательный, увеличьте уровень на 1, в противном случае возьмите минимум. ? Спасибо

3. Да — таким образом, то, как я это сделал, показало бы вам пороговую полосу, в которую оно попало. Если оно упало на -2, -1, вы хотите назвать его -1, потому что оно прошло -1, если оно упало на 1,2, вы хотите назвать его 1. В столбце alarmlevel если вы возьмете минимальное значение первой части этого значения (-2 из-2, -1 или 1 из 1,2), вы получите правильный alarm # для 1,2, но у -2, -1 должен быть уровень тревоги -1. Итак, если оно отрицательное, то есть оно захватывает значение -2, добавьте к нему единицу, чтобы получить сигнал тревоги -1

4. да, верно, я на самом деле печатал ответ для этого.

5. Я обновил свой код, чтобы в нем были сдвиги groupby, чтобы он не переходил в другую группу. сдвиги groupby будут сдвигаться внутри каждой указанной группы, и тогда в конце она будет иметь нулевое значение, поскольку сдвигать дальше 3 нечего. Итак, мы заполняем это высокое пороговое значение бесконечностью из numpy и называем это пороговое значение 4.