Заполнение значений линейно в обратном направлении с помощью groupby

#python #pandas #lambda #pandas-groupby #interpolation

#python #pandas #лямбда #pandas-groupby #интерполяция

Вопрос:

У меня есть этот df:

 df = pd.DataFrame({"Time": [nat, '2020-04-09 06:46:00', '2020-04-09 06:46:00', '2020-04-09 06:46:00', '2020-04-09 06:46:00', '2020-04-09 06:46:00', nat, '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515'],
                  "Power": [0, 0, 0, 0, 4200, 4200, 0, 4200, 4200, 4200, 5000],
                  "Total Energy": [5200, 5200, 5200, 5200, 5500, 5600, 5600, 5600, 5600, 5900, 6100],
                  "ID": ['-', 1, 1, 1, 1, 1, '-', 2, 2, 2, 2],
                  "Energy": [0, 0, 0, 0, 300, 400, 0, 0, 0, 300, 500]},
                  index=pd.date_range(start = "2020-04-09 6:45", periods = 11, freq = 'T'))
    
df['Time'] = pd.to_datetime(df['Time'])
df['Power'] = pd.to_numeric(df['Power'], errors = 'ignore')
df['Total Energy'] = pd.to_numeric(df['Total Energy'], errors = 'coerce')
df['ID'] = pd.to_numeric(df['ID'], errors = 'coerce')
df['Energy'] = pd.to_numeric(df['Energy'], errors = 'coerce')
    
df
  

Вывод:

                                           Time  Power   Total Energy     ID Energy
2020-04-09 06:45:00                        NaT     0            5200    NaN      0
2020-04-09 06:46:00 2020-04-09 06:46:00.000000     0            5200    1.0      0
2020-04-09 06:47:00 2020-04-09 06:46:00.000000     0            5200    1.0      0
2020-04-09 06:47:00 2020-04-09 06:46:00.000000     0            5200    1.0      0
2020-04-09 06:48:00 2020-04-09 06:46:00.000000  4200            5500    1.0    300
2020-04-09 06:49:00 2020-04-09 06:46:00.000000  4200            5600    1.0    400
2020-04-09 06:50:00                        NaT     0            5600    NaN      0
2020-04-09 06:51:00 2020-04-09 06:50:16.268515  4200            5600    2.0      0
2020-04-09 06:51:00 2020-04-09 06:50:16.268515  4200            5600    2.0      0
2020-04-09 06:52:00 2020-04-09 06:50:16.268515  4200            5900    2.0    300
2020-04-09 06:53:00 2020-04-09 06:50:16.268515  5000            6100    2.0    500
  

Я хочу заполнить столбец df['Energy'] линейно — групповым столбцом `df[‘Time’] (начиная с 0).

Ожидаемый результат:

                                           Time  Power   Total Energy     ID Energy
2020-04-09 06:45:00                        NaT     0            5200    NaN      0
2020-04-09 06:46:00 2020-04-09 06:46:00.000000     0            5200    1.0      0
2020-04-09 06:47:00 2020-04-09 06:46:00.000000     0            5200    1.0    100
2020-04-09 06:47:00 2020-04-09 06:46:00.000000     0            5200    1.0    200
2020-04-09 06:48:00 2020-04-09 06:46:00.000000  4200            5500    1.0    300
2020-04-09 06:49:00 2020-04-09 06:46:00.000000  4200            5600    1.0    400
2020-04-09 06:50:00                        NaT     0            5600    NaN      0
2020-04-09 06:51:00 2020-04-09 06:50:16.268515  4200            5600    2.0      0
2020-04-09 06:51:00 2020-04-09 06:50:16.268515  4200            5600    2.0    150
2020-04-09 06:52:00 2020-04-09 06:50:16.268515  4200            5900    2.0    300
2020-04-09 06:53:00 2020-04-09 06:50:16.268515  5000            6100    2.0    500
  

Я пробовал это: df['Energy'] = df.groupby('Time')['Energy'].apply(lambda x: x.interpolate()) , но это не сработало.

Ответ №1:

Проблема не в вашем коде — она в данных и использовании интерполяции.

Функция interpolate() используется для заполнения значений NA в фрейме данных или серии… но в вашем фрейме данных — энергетический ряд имеет ‘0s’, которые не будут применены при интерполяции.

Я внес незначительные изменения в ваши данные, чтобы продемонстрировать. Обратите внимание, что энергетический ряд изменился, чтобы иметь np.nan в областях, которые вы хотите «интерполировать»

 df = pd.DataFrame({"Time": [nat, '2020-04-09 06:46:00', '2020-04-09 06:46:00', '2020-04-09 06:46:00', '2020-04-09 06:46:00', '2020-04-09 06:46:00', nat, '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515'],
                  "Power": [0, 0, 0, 0, 4200, 4200, 0, 4200, 4200, 4200, 5000],
                  "Total Energy": [5200, 5200, 5200, 5200, 5500, 5600, 5600, 5600, 5600, 5900, 6100],
                  "ID": ['-', 1, 1, 1, 1, 1, '-', 2, 2, 2, 2],
                  "Energy": [np.nan, 0, np.nan, np.nan, 300, 400, np.nan, 0, np.nan, 300, 500]},
                  index=pd.date_range(start = "2020-04-09 6:45", periods = 11, freq = 'T'))
  

ТЕПЕРЬ, когда вы запускаете это…

 df['Energy'] = df.groupby('Time')['Energy'].apply(lambda x: x.interpolate())
print(df)
  

Вы получите это:

                                       Time  Power  Total Energy   ID  Energy
2020-04-09 06:45:00                        NaT      0          5200  NaN     NaN
2020-04-09 06:46:00 2020-04-09 06:46:00.000000      0          5200  1.0     0.0
2020-04-09 06:47:00 2020-04-09 06:46:00.000000      0          5200  1.0   100.0
2020-04-09 06:48:00 2020-04-09 06:46:00.000000      0          5200  1.0   200.0
2020-04-09 06:49:00 2020-04-09 06:46:00.000000   4200          5500  1.0   300.0
2020-04-09 06:50:00 2020-04-09 06:46:00.000000   4200          5600  1.0   400.0
2020-04-09 06:51:00                        NaT      0          5600  NaN     NaN
2020-04-09 06:52:00 2020-04-09 06:50:16.268515   4200          5600  2.0     0.0
2020-04-09 06:53:00 2020-04-09 06:50:16.268515   4200          5600  2.0   150.0
2020-04-09 06:54:00 2020-04-09 06:50:16.268515   4200          5900  2.0   300.0
2020-04-09 06:55:00 2020-04-09 06:50:16.268515   5000          6100  2.0   500.0
  

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