Генерация исходящего фрейма данных на основе операции пересечения нуля в среднем - PullRequest
1 голос
/ 12 апреля 2020

У меня есть следующий входной фрейм данных:

      import numpy as np
      import pandas as pd

      df = pd.DataFrame({'IDsensor': [1, 1, 4, 4, 4], 
                         'Sensor_SYS1_All': [54, 55, 75, 40, 58],
                         'Sensor_SYS2_All': [320, 315, 400, 300, 401]})

      print(df)

      # Output:
        IDsensor    Sensor_SYS1_All  Sensor_SYS2_All
          1               54              320
          1               55              315
          4               75              400
          4               40              300
          4               58              401

На основе этого фрейма мне нужно было сгруппировать по IDsensor для расчета среднего. Итак, я реализовал следующий код:

       df_Mean = df.groupby('IDsensor', as_index=False)[['Sensor_SYS1_All','Sensor_SYS2_All']].mean()

       df_Mean.rename(columns={'Sensor_SYS1_All': 'Sensor_SYS1_Mean',
                               'Sensor_SYS2_All': 'Sensor_SYS2_Mean',
                              }, inplace=True)
       print(df_Mean)

       # Output:
        IDsensor    Sensor_SYS1_Mean    Sensor_SYS2_Mean
             1          54.500000           317.5
             4          57.666667           367.0

Теперь мне нужно сделать тот же процесс. На этот раз вместо вычисления среднего значения по группе мне нужно рассчитать, сколько раз значения датчика пересекают среднее значение.

Примечание: это похоже на операцию «пересечения нуля», но вместо этого для вычисления пересечения нулевого значения, это будет среднее значение.

Я попытался сделать следующую функцию:

         def zero_crossing_avg(array_data, var_mean):
              crossMean = np.sum((array_data[:-1] > var_mean) != (array_data[1:] > var_mean))

              return(crossMean)

Примечание: эта функция работает. Функция возвращает количество пересечений среднего значения. Однако он не создается автоматически и не генерирует кадр данных ответа (как в случае средней операции).

       # IDsensor = 1 for Sensor_SYS1_All
       zero_crossing_avg(np.array([54,55]), 54.500000)
       # Output: 1

       #  # IDsensor = 1 for Sensor_SYS2_All
       zero_crossing_avg(np.array([320,315]), 317.5)
       zero_crossing_avg(np.array([320,315]), 317.5)
       # Output: 1

       # IDsensor = 4 for Sensor_SYS1_All
       zero_crossing_avg(np.array([75,40, 58]), 57.666667)
       # Output: 2

       # IDsensor = 4 for Sensor_SYS2_All
       zero_crossing_avg(np.array([400,300, 401]), 367.0)
       # Output: 2

Я бы хотел, чтобы вы автоматически генерировали этот кадр данных ответа:

         IDsensor   Sensor_SYS1_Cross   Sensor_SYS2_Cross
             1              1                 1
             4              2                 2

1 Ответ

1 голос
/ 12 апреля 2020

Вы можете использовать groupby и преобразовать mean, чтобы преобразовать средние значения для столбцов в кадре данных, кроме столбца группировщика, а затем сравнить, если значения в этом кадре больше, чем средние значения, затем в столбец groupby IDsensor и взять сумму booleans:

out = (df.drop('IDsensor',1).gt(df.groupby('IDsensor').transform('mean'))
                              .groupby(df['IDsensor']).sum().astype(int))
out = out.rename(columns = lambda x: f"{x.rsplit('_',1)[0]}_Cross").reset_index()

print(out)

   IDsensor  Sensor_SYS1_Cross  Sensor_SYS2_Cross
0         1                  1                  1
1         4                  2                  2

Здесь вы можете увидеть, что делает преобразование:

print(df.groupby('IDsensor').transform('mean'))

    Sensor_SYS1_All  Sensor_SYS2_All
0        54.500000            317.5
1        54.500000            317.5
2        57.666667            367.0
3        57.666667            367.0
4        57.666667            367.0

Примечание: если вы хотите это указать для c 2 столбца, замените df.groupby('IDsensor').transform('mean') на df.groupby('IDsensor')[list_of_column_names].transform('mean') и сравните только эти столбцы df[list_of_column_names].gt(df.groupby....), как показано ниже:

col_list = ['Sensor_SYS1_All','Sensor_SYS2_All']
out = (df[col_list].gt(df.groupby('IDsensor')[col_list].transform('mean'))
                              .groupby(df['IDsensor']).sum().astype(int))
out = out.rename(columns = lambda x: f"{x.rsplit('_',1)[0]}_Cross").reset_index()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...