#python #pandas #dataframe
#python #панды #фрейм данных
Вопрос:
У меня есть передискретизированный df:
import pandas as pd
import numpy as np
nat = np.datetime64('NaT')
df = pd.DataFrame({"Time": [nat, nat, nat, '2020-04-09 06:45:38.559871', '2020-04-09 06:45:38.559871', nat, nat, nat, '2020-04-09 06:50:16.268515', '2020-04-09 06:50:16.268515'],
"Power": [0, 0, 0, 4200, 4200, 0, 0, 0, 4200, 4200],
"Total Energy": [5300, 5300, 5300, 5500, 5600, 5600, 5600, 5600, 5900, 6100],
"ID": ['-', '-', '-', 1, 1, '-', '-', '-', 2, 2],
"Energy": [0, 0, 0, 200, 300, 0, 0, 0, 300, 500]},
index=pd.date_range(start = "2020-04-09 6:45", periods = 10, 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 5300 NaN 0
2020-04-09 06:46:00 NaT 0 5300 NaN 0
2020-04-09 06:47:00 NaT 0 5300 NaN 0
2020-04-09 06:48:00 2020-04-09 06:45:38.559871 4200 5500 1.0 200
2020-04-09 06:49:00 2020-04-09 06:45:38.559871 4200 5600 1.0 300
2020-04-09 06:50:00 NaT 0 5600 NaN 0
2020-04-09 06:51:00 NaT 0 5600 NaN 0
2020-04-09 06:52:00 NaT 0 5600 NaN 0
2020-04-09 06:53:00 2020-04-09 06:50:16.268515 4200 5900 2.0 300
2020-04-09 06:54:00 2020-04-09 06:50:16.268515 4200 6100 2.0 500
Я должен заполнить строки, где df.index < df['Time']
(округлено) и df['Time'] == NaT
следующим образом:
df.index == df['Time']: df['Power'] = 0, df['Total Energy']
остается прежним,df['ID'] = df['ID'] of the df['Time'], df['Energy'] = 0
- между этими двумя строками записи должны быть заполнены следующим образом:
df['Power'] = df['Energy']
@df['Time'] / ((df['Time'] (rounded) - df.index)/60)
,df['Energy'] = df['Power'] * 1/60, df['Total Energy'] = df['Total Energy'].shift(1) df['Energy'], df['ID'] = df['ID']
изdf['Time']
вот желаемый результат:
Time Power Total Energy ID Energy
2020-04-09 06:45:00 NaT 0 5300 NaN 0
2020-04-09 06:46:00 2020-04-09 06:45:38.559871 0 5300 1.0 0
2020-04-09 06:47:00 2020-04-09 06:45:38.559871 6000 5400 1.0 100
2020-04-09 06:48:00 2020-04-09 06:45:38.559871 4200 5500 1.0 200
2020-04-09 06:49:00 2020-04-09 06:45:38.559871 4200 5600 1.0 300
2020-04-09 06:50:00 NaT 0 5600 NaN 0
2020-04-09 06:51:00 2020-04-09 06:50:16.268515 0 5600 2.0 0
2020-04-09 06:52:00 2020-04-09 06:50:16.268515 9000 5750 2.0 150
2020-04-09 06:53:00 2020-04-09 06:50:16.268515 4200 5900 2.0 300
2020-04-09 06:54:00 2020-04-09 06:50:16.268515 4200 6100 2.0 500
столбец df['Time']
также может быть изменен на округленное значение:
Time Power Total Energy ID Energy
2020-04-09 06:45:00 NaT 0 5300 NaN 0
2020-04-09 06:46:00 2020-04-09 06:46:00 0 5300 1.0 0
2020-04-09 06:47:00 2020-04-09 06:46:00 6000 5400 1.0 100
2020-04-09 06:48:00 2020-04-09 06:46:00 4200 5500 1.0 200
2020-04-09 06:49:00 2020-04-09 06:46:00 4200 5600 1.0 300
2020-04-09 06:50:00 NaT 0 5600 NaN 0
2020-04-09 06:51:00 2020-04-09 06:51:00 0 5600 2.0 0
2020-04-09 06:52:00 2020-04-09 06:51:00 9000 5750 2.0 150
2020-04-09 06:53:00 2020-04-09 06:51:00 4200 5900 2.0 300
2020-04-09 06:54:00 2020-04-09 06:51:00 4200 6100 2.0 500
Спасибо за вашу помощь 🙂
Редактировать
чтобы округлить df['Time']
, я нашел это:
df['Time'] = df['Time'].dt.ceil('1min')
Редактировать 2
чтобы настроить столбец df['Time']
, я поступил следующим образом:
dates = df['Time'].unique()
for date in dates:
for index, row in df.iterrows():
if index == date:
df.loc[index, 'Time'] = date
как я получаю df[ID]
из соответствующего столбца ( df['Time']
), я пока не знаю.
Я также заполнил строки следующим образом:
#scheme for filling the nan-values
s = df['Time'].ffill()
x = df['Time'].bfill()
g = df['Time'].mask(s.eq(x), s)
#Filling time
df['Time'] = df['Time'].groupby(g).ffill()
#Filling ID
df3['ID'] = df2['ID'].groupby(df2['Time']).bfill()
Вывод:
Time Power Total Energy ID Energy
2020-04-09 06:45:00 NaT 0 5300 NaN 0
2020-04-09 06:46:00 2020-04-09 06:46:00 0 5300 1.0 0
2020-04-09 06:47:00 2020-04-09 06:46:00 0 5300 1.0 0
2020-04-09 06:48:00 2020-04-09 06:46:00 4200 5500 1.0 200
2020-04-09 06:49:00 2020-04-09 06:46:00 4200 5600 1.0 300
2020-04-09 06:50:00 NaT 0 5600 NaN 0
2020-04-09 06:51:00 2020-04-09 06:51:00 0 5600 2.0 0
2020-04-09 06:52:00 2020-04-09 06:51:00 0 5600 2.0 0
2020-04-09 06:53:00 2020-04-09 06:51:00 4200 5900 2.0 300
2020-04-09 06:54:00 2020-04-09 06:51:00 4200 6100 2.0 500
этого все еще не хватает: значения для df['Power']/ df['Energy']
и df['Total Energy']
должны быть рассчитаны и изменены, как описано выше.
Комментарии:
1. Интересный, но слишком специфичный вопрос. В подобных случаях вам следует лучше объяснить, как вам нужно реализовать преобразования данных. Пожалуйста, улучшите способ объяснения формул для обновления
power
столбца.2. Спасибо за ваш совет! Большинство пунктов я проанализировал и добавил сам, для людей, у которых есть подобные проблемы. Для столбца необходим
power
столбецenergy
.power = energy*60
. Для столбцаenergy
достаточно, если он заполнен линейно, если естьtime
запись.Total Energy
может быть вычислен путем сложения или вычитания последнего значенияenergy
. Я надеюсь, что это прояснит мою проблему, и вы сможете помочь справиться с ней 🙂 Спасибо
Ответ №1:
Учитывая ваш желаемый результат и то, что вы сказали мне в своем комментарии, я сделал это:
time_bfill = df['Time'].bfill()
df['Time2'] = df['Time'].mask(df.index.to_series().ge(time_bfill), time_bfill)
id_bfill = df['ID'].bfill()
df['ID2'] = df['ID'].mask(df.index.to_series().ge(time_bfill), id_bfill)
df['Energy2'] = df['Energy'].mask((df['Time'].isnull()) amp; (df['Time2'].notna()) amp; (df.index.to_series().ne(df['Time2'])), np.NaN)
df['Energy3'] = df['Energy2'].interpolate(limit_direction='both', limit_area='inside')
df['Power2'] = df['Power'].mask(df['Power'] == 0, 60 * df['Energy3'])
df['Total Energy2'] = df['Total Energy'].mask(df['Power'] == 0, df['Total Energy'] df['Energy3'])
df
и получил этот фрейм данных:
Рассмотрим столбцы с наибольшими суффиксами. Я оставил их здесь, чтобы вы могли увидеть промежуточные шаги.
Вы можете настроить этот код так, чтобы избежать некоторых промежуточных столбцов, но будьте осторожны, поскольку в некоторых случаях исходные значения необходимы другим столбцам, сгенерированным после них.
Быстрый способ избавиться от этих промежуточных столбцов — запустить это в конце:
df[['Time', 'Power', 'Total Energy', 'ID', 'Energy']] = df[['Time2', 'Power2', 'Total Energy2', 'ID2', 'Energy3']]
df.drop(['Time2', 'Power2', 'Total Energy2', 'ID2', 'Energy3', 'Energy2'], axis=1, inplace=True)
df
и вы получаете: