在熊猫数据框中填写缺少的时间

时间:2018-09-19 15:46:11

标签: python pandas

我有一个包含每小时数据的数据框:

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的所有小时,然后将我的数据与该数据框合并,然后用0填充NaN。这非常慢,因为我的数据集可以包含数百万行。

还有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

您可以使用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

答案 1 :(得分:1)

您可以创建日期范围的最大值和最小值,并将数据框与现有数据合并,并使用null填充值

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

出局:

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

答案 2 :(得分:0)

Wen 提出的解决方案只要源日期/时间来自 单个测量日。

如果来源包含不同天的读数,则重新采样的结果 从第一天的最早阅读到最新 在最后一天阅读的内容,包括夜间时段,什么是 可能不是您想要的。

该解决方案的另一个缺点是它不提供“零”读数 从测量的一开始就开始,但是从最早的阅读开始。 同样适用于“最终”阅读,也不一定在末尾 测量日。

我的解决方案没有这些缺点,它基于以下假设:

  1. 保留源 date 列,因为稍后将需要。 计算 Datetime 后,仅删除 hour 列。
  2. 生成包含 NaN 读数的 df_borders 数据框,以开始/结束 在每个区域和日期的测量日,我假设为 07:00:00 13:00:00
  3. 将上述 NaN 读数添加到主DataFrame中,并删除每个重复项 区域 / DateTime 。这样,每个区域/天的源数据就包含了 每天确切开始/结束的读数,无论是原始的还是从 df_borders
  4. 为避免出现“工作日外”的读数,必须在以下位置进行分组 ['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

根据需要,提供3个区域/日期对的一系列7个读数。