Найти и заполнить недостающее время во фрейме данных

#python #pandas #date #datetime #missing-data

#python #pandas #Дата #дата и время #отсутствует-данные

Вопрос:

мы работаем над фреймом данных pandas, который выглядит как показано ниже. Здесь столбец времени имеет приращение в 15 минут, и есть несколько отсутствующих записей времени. Мы хотим заполнить недостающие записи времени соответствующей датой и заполнить все соответствующие поля нулями. Вот как выглядит фрейм данных.

 df=
date.y        timeslot_1  ProductId PlantId region  UserId  Gender  AgeGroup    Weights
6/07/2018   1:15:00         1002    8577       6      Mab   2           S       1432.6
6/07/2018   1:15:00         1002    8577       6      Mac   2           M       1629.3
6/07/2018   1:15:00         1001    8647       6      Maa   2           P       5299.6
6/07/2018   1:45:00         1001    7636       C      Mab   1           T       1626.4
6/07/2018   1:45:00         1002    8577       6      Maa   1           T       1476.1
6/07/2018   1:45:00         1002    8577       6      Mab   2           S       1432.6
6/07/2018   1:45:00         1002    8577       6      Mac   2           M       1629.3
6/07/2018   1:45:00         1001    8647       6      Maa   2           P       5299.6
6/07/2018   2:00:00         1001    8647       6      Maa   2           P       4731.6
6/07/2018   2:15:00         1001    7636       C      Mab   1           T       1638.6
6/07/2018   2:15:00         1002    8808       C      Maa   2           M       2465.3
6/07/2018   2:30:00         1002    7491       4      Mab   1           N       5419.8
6/07/2018   2:45:00         1002    7491       4      Mab   1           N       5419.8
6/07/2018   3:15:00         1001    8362       6      Maa   2           X       2227.6
6/07/2018   3:15:00         1002    8714       C      Maa   2           P       1820.6
6/07/2018   3:15:00         1001    8668       5      Mab   2           S       2048.4
6/07/2018   4:00:00         1002    8714       C      Maa   2           P       1820.6
  

Мы подумали о создании другого базового файла, который содержал бы все увеличенное на 15 минут время с соответствующей датой, а затем объединил базовый файл с исходным фреймом данных. Однако некоторые из них, похоже, не работают. Объединение просто помещает все места из базового файла в конец каждой даты. Вот как выглядит объединенный фрейм данных.

 date.y        timeslot_1    ProductId    PlantId    region    UserId    Gender    AgeGroup    Weights
6/7/2018         1:15:00        1002        8577    6           Mab         2       S        1432.6
6/7/2018         1:15:00        1002        8577    6           Mac         2       M        1629.3
6/7/2018         1:15:00        1001        8647    6           Maa         2       P        5299.6
6/7/2018         1:45:00        1001        7636    C           Mab         1       T        1626.4
6/7/2018         1:45:00        1002        8577    6           Maa         1       T        1476.1
6/7/2018         1:45:00        1002        8577    6           Mab         2       S        1432.6
6/7/2018         1:45:00        1002        8577    6           Mac         2       M        1629.3
6/7/2018         1:45:00        1001        8647    6           Maa         2       P        5299.6
6/7/2018         2:00:00        1001        8647    6           Maa         2       P        4731.6
6/7/2018         2:15:00        1001        7636    C           Mab         1       T        1638.6
6/7/2018         2:15:00        1002        8808    C           Maa         2       M        2465.3
6/7/2018         2:30:00        1002        7491    4           Mab         1       N        5419.8
6/7/2018         2:45:00        1002        7491    4           Mab         1       N        5419.8
6/7/2018         3:15:00        1001        8362    6           Maa         2       X        2227.6
6/7/2018         3:15:00        1002        8714    C           Maa         2       P        1820.6
6/7/2018         3:15:00        1001        8668    5           Mab         2       S        2048.4
6/7/2018         4:00:00        1002        8714    C           Maa         2       P        1820.6
6/7/2018         1:15:00                            
6/7/2018         1:30:00                            
6/7/2018         1:45:00                            
6/7/2018         2:00:00                            
6/7/2018         2:15:00                            
6/7/2018         2:30:00                            
6/7/2018         2:45:00                            
6/7/2018         3:00:00                            
6/7/2018         3:15:00                            
6/7/2018         3:30:00                            
6/7/2018         3:45:00              
  

Ниже приведен код

 
date1='06/03/2018'
date2='06/10/2018'
d=pd.date_range(start=date1  ' 02:00:00', end=date2 ' 02:00:00', freq='15min')
columns=['date']
all_spots=pd.DataFrame(columns=columns)
all_spots=all_spots.assign(date=d)
all_spots=all_spots.astype(str)
all_spots = pd.DataFrame(all_spots.date.str.split(' ',1).tolist(),columns = ['date.y','timeslot_1'])
d=pd.merge(df,all_spots,how='outer', on=['date.y','timeslot_1'])
  

Вот как будет выглядеть результат.

 date.y        timeslot_1  ProductId PlantId region  UserId  Gender  AgeGroup    Weights
6/07/2018   1:15:00         1002    8577       6      Mab   2           S       1432.6
6/07/2018   1:15:00         1002    8577       6      Mac   2           M       1629.3
6/07/2018   1:15:00         1001    8647       6      Maa   2           P       5299.6
6/07/2018   1:30:00           0      0         0       0    0           0         0
6/07/2018   1:45:00         1001    7636       C      Mab   1           T       1626.4
6/07/2018   1:45:00         1002    8577       6      Maa   1           T       1476.1
6/07/2018   1:45:00         1002    8577       6      Mab   2           S       1432.6
6/07/2018   1:45:00         1002    8577       6      Mac   2           M       1629.3
6/07/2018   1:45:00         1001    8647       6      Maa   2           P       5299.6
6/07/2018   2:00:00         1001    8647       6      Maa   2           P       4731.6
6/07/2018   2:15:00         1001    7636       C      Mab   1           T       1638.6
6/07/2018   2:15:00         1002    8808       C      Maa   2           M       2465.3
6/07/2018   2:30:00         1002    7491       4      Mab   1           N       5419.8
6/07/2018   2:45:00         1002    7491       4      Mab   1           N       5419.8
6/07/2018   3:00:00           0      0         0       0    0           0         0
6/07/2018   3:15:00         1001    8362       6      Maa   2           X       2227.6
6/07/2018   3:15:00         1002    8714       C      Maa   2           P       1820.6
6/07/2018   3:15:00         1001    8668       5      Mab   2           S       2048.4
6/07/2018   3:30:00           0      0         0       0    0           0         0
6/07/2018   3:45:00           0      0         0       0    0           0         0
6/07/2018   4:00:00         1002    8714       C      Maa   2           P       1820.6
  

PS Следует отметить, что это всего лишь фрагмент данных. У нас есть данные за один месяц. Итак, нам нужно позаботиться о дате, а время указано в 24-часовом формате.

Мы надеялись, что кто-нибудь может помочь решить эту проблему.

Заранее большое спасибо!!

Ответ №1:

Я думаю, вам нужно создать еще один фрейм данных для объединения с вашим фреймом данных.

 # Change "1:15", "4:00" to "0:00, 23:59" for your actual data.
hr_range = pd.date_range("1:15", "4:00", freq="15min").strftime('%H:%M:%S')

# Remove 0 to match your format
hr_range = hr_range.str.lstrip('0')

df2 = pd.DataFrame()
df2['timeslot_1'] = hr_range
df2['date.y'] = pd.to_datetime('2018-06-07')
  

Затем преобразуйте date.y в datetime и set_index оба фрейма данных с ['date.y', 'timeslot_1'] помощью .

 df['date.y'] = pd.to_datetime(df['date.y'])

df.set_index(['date.y', 'timeslot_1'], inplace=True)
df2.set_index(['date.y', 'timeslot_1'], inplace=True)
  

И join их вместе с how='outer'

 df.join(df2, how='outer').fillna(0).reset_index()
  

Альтернативное решение без использования .set_index

 (df.merge(df2, on=['date.y', 'timeslot_1'], how='outer')
   .sort_values(['date.y', 'timeslot_1'])
   .fillna(0))
  

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

1. Большое спасибо за ответ. Следует отметить, что date.y это не одна дата. Это также диапазон дат. Мы создали диапазон, используя pd.date_range(start=date1 ' 02:00:00', end=date2 ' 02:00:00', freq='15min') . однако нам пришлось преобразовать это в строку, чтобы разделить их по датам и времени в отдельном столбце. Кроме того, дата и время в исходном фрейме данных имеют формат даты и времени. Рекомендуете ли вы преобразовывать их в строку при создании формата hr_range in string

2. @AnalyticsTeam Вы можете использовать pd.date_rage(start_date, end_date) вместо одной даты. Также, прежде чем разбивать ваше datetime на дату и время, вы можете использовать ваше pd.date_range , а set_index затем join их вместе. Я должен преобразовать его, чтобы string сделать его совместимым с вашим примером фрейма данных.