Заполните пропущенные часы в кадре данных панд - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть фрейм данных, который содержит почасовые данные:

area     date         hour      output
H1       2018-07-01   07:00:00  150
H1       2018-07-01   08:00:00  150
H1       2018-07-01   09:00:00  100
H1       2018-07-01   11:00:00  150
H2       2018-07-01   09:00:00  100
H2       2018-07-01   10:00:00   50
H2       2018-07-01   11:00:00   50
H2       2018-07-01   12:00:00  150

, но данные содержат строку только для часов, когда был вывод, как я могу заполнить пропущенные часы для каждой области с выводом 0?Например, добавьте две строки для H1:

area     date         hour      output
H1       2018-07-01   10:00:00  0
H1       2018-07-01   12:00:00  0

Я могу предположить, что минимальный и максимальный час для всех областей являются началом и концом периода выборки (в данном случае 7:00:00 и 12:00:00)

Сейчас я создаю фрейм данных, содержащий все часы с 7:00 до 12:00 для каждой области, а затем выполняю слияние моих данных с этим фреймом, а затем заполняюNaN с 0с.Это очень медленно, так как мой набор данных может содержать миллионы строк.

Есть ли лучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Вы можете создать диапазон дат min и max и объединить ваш фрейм данных с существующими значениями и заполнить их значениями с нулем

df

    area    date    hour    output
0   H1  2018-07-01 07:00:00 07:00:00    150
1   H1  2018-07-01 08:00:00 08:00:00    150
2   H1  2018-07-01 09:00:00 09:00:00    100
6   H2  2018-07-01 11:00:00 11:00:00    50
7   H2  2018-07-01 12:00:00 12:00:00    150

df = pd.DataFrame(pd.date_range(pd.to_datetime(df['date'] +' ' + df['hour']).min(),pd.to_datetime(df['date'] +' ' + df['hour']).max(),freq='H'),columns= ['date']).merge(df,on=['date'],how='outer').fillna(0)
df.hour = df.date.dt.strftime('%H:%M:%S')
df.date = df.date.dt.strftime('%d-%m-%Y')
df

Out:

date    area    hour    output
0   01-07-2018  H1  07:00:00    150.0
1   01-07-2018  H1  08:00:00    150.0
2   01-07-2018  H1  09:00:00    100.0
3   01-07-2018  0   10:00:00    0.0
4   01-07-2018  H2  11:00:00    50.0
5   01-07-2018  H2  12:00:00    150.0
0 голосов
/ 20 сентября 2018

Решение, предложенное Вен , работает, пока даты / время источника взяты из одного дня измерения.

Если источник содержал показания из в разное дней, результат повторная выборка для каждой области будет от самого раннего чтения в первый день до самого последнего чтения в последний день , включая промежуточные ночные часы , что, вероятно, не то, что вам нужно.

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

Мое решение, свободное от этих недостатков, основано на следующих предположениях:

  1. Оставьте исходный столбец date , так как он понадобится позже.После вычисления Datetime только столбец сброса hour .
  2. Generate df_borders DataFrame, содержащий NaN показания для начала / концадня измерения, для каждой области и даты, я предположил для 07: 00: 00 и 13: 00: 00 .
  3. Добавить вышеуказанное NaN показания на основной DataFrame и удаление дубликатов для каждой области / DateTime .Таким образом, исходные данные для каждой области / дня содержат показания для точного начала / конца каждого дня, либо оригинальные, либо добавленные из df_borders .
  4. Чтобы избежать "не рабочего дняmsgstr "чтения, группировка должна выполняться на ['area', 'date'] .Вот почему я оставил столбец date до сих пор.
  5. Теперь столбец date не нужен и его можно удалить.
  6. Последний шаг -распечатать результат.

Ниже приведен пример программы:

import pandas as pd

df = pd.read_csv('Input.csv')

# Generate df_borders - NaN readings for start / end of each area / date
df_start = df[['area','date']].drop_duplicates()
df_end = df_start.copy()
df_start['hour'] = '07:00:00'
df_end['hour'] = '13:00:00'
df_borders = pd.concat([df_start,df_end])

# Compute Datetime column and drop hour column, for both DataFrames
df['Datetime'] = pd.to_datetime(df.date + ' ' + df.hour)
df.drop('hour', inplace=True, axis = 1)
df_borders['Datetime'] = pd.to_datetime(df_borders.date + ' ' + df_borders.hour)
df_borders.drop('hour', inplace=True, axis = 1)

# Add NaN readings
df = df.append(df_borders, sort=False, ignore_index=True)\
    .drop_duplicates(subset=['area', 'Datetime'])

# Generate the full set of readings
df = df.groupby(['area', 'date'])\
    .apply(lambda x : x.set_index('Datetime').resample('H').mean().fillna(0))\
    .reset_index()
df.drop('date', inplace=True, axis = 1)

# Result
print(df)

Некоторые части являются копией решения Wen , чтобы избежать повторного изобретенияколесо.

Для исходных данных:

area,date,hour,output
H1,2018-07-01,07:00:00,150
H1,2018-07-01,08:00:00,120
H1,2018-07-01,09:00:00,90
H1,2018-07-01,11:00:00,130
H2,2018-07-01,09:00:00,110
H2,2018-07-01,10:00:00,50
H2,2018-07-01,11:00:00,80
H2,2018-07-01,12:00:00,110
H2,2018-07-02,08:00:00,40
H2,2018-07-02,09:00:00,65
H2,2018-07-02,11:00:00,95
H2,2018-07-02,12:00:00,45

он печатает:

   area            Datetime  output
0    H1 2018-07-01 07:00:00   150.0
1    H1 2018-07-01 08:00:00   120.0
2    H1 2018-07-01 09:00:00    90.0
3    H1 2018-07-01 10:00:00     0.0
4    H1 2018-07-01 11:00:00   130.0
5    H1 2018-07-01 12:00:00     0.0
6    H1 2018-07-01 13:00:00     0.0
7    H2 2018-07-01 07:00:00     0.0
8    H2 2018-07-01 08:00:00     0.0
9    H2 2018-07-01 09:00:00   110.0
10   H2 2018-07-01 10:00:00    50.0
11   H2 2018-07-01 11:00:00    80.0
12   H2 2018-07-01 12:00:00   110.0
13   H2 2018-07-01 13:00:00     0.0
14   H2 2018-07-02 07:00:00     0.0
15   H2 2018-07-02 08:00:00    40.0
16   H2 2018-07-02 09:00:00    65.0
17   H2 2018-07-02 10:00:00     0.0
18   H2 2018-07-02 11:00:00    95.0
19   H2 2018-07-02 12:00:00    45.0
20   H2 2018-07-02 13:00:00     0.0

При необходимости, серия из 7 показаний, для 3 пар зона / дата.

0 голосов
/ 19 сентября 2018

Вы можете проверить resample с groupby

df['Datetime']=pd.to_datetime(df.date+' '+df.hour)# combine hour and date to datetime 

df.drop(['date','hour'],inplace=True,axis = 1)# drop duplicate infomation
df.groupby('area').\
    apply(lambda x : x.set_index('Datetime').resample('H').mean().fillna(0)).\
      reset_index()
Out[662]: 
  area            Datetime  output
0   H1 2018-07-01 07:00:00   150.0
1   H1 2018-07-01 08:00:00   150.0
2   H1 2018-07-01 09:00:00   100.0
3   H1 2018-07-01 10:00:00     0.0
4   H1 2018-07-01 11:00:00   150.0
5   H2 2018-07-01 09:00:00   100.0
6   H2 2018-07-01 10:00:00    50.0
7   H2 2018-07-01 11:00:00    50.0
8   H2 2018-07-01 12:00:00   150.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...