【问题标题】:Find missing values of datetime for every customer查找每个客户的日期时间缺失值
【发布时间】:2019-07-01 01:08:47
【问题描述】:
    CustID  UsageDate               EnergyConsumed
0   17111   2018-01-01 00:00:00     1.095
1   17111   2018-01-01 01:00:00     1.129
2   17111   2018-01-01 02:00:00     1.165
3   17111   2018-01-01 03:00:00     1.833
4   17111   2018-01-01 04:00:00     1.697
5   17111   2018-01-01 05:00:00     1.835
missing data point 1
6   17111   2018-01-01 07:00:00     1.835
7   17112   2018-01-01 00:00:00     1.095
8   17112   2018-01-01 01:00:00     1.129
missing data point 1
9   17112   2018-01-01 03:00:00     1.833
10  17112   2018-01-01 04:00:00     1.697
11  17112   2018-01-01 05:00:00     1.835

对于每个客户,我都有每小时的数据。但是,两者之间缺少一些数据点。我想检查使用日期的最小值和最大值,并在该时间间隔内填写缺失的使用日期(所有值都是每小时),并将 EnergyConsumed 设为零。我以后可以使用 ffill 或 backfill 来解决这个问题。

并非每个客户的最大 UsageDate 是 2018-01-31 23:00:00。所以我们只想将系列延长到每个客户的最大日期。

缺少的点1被替换为

17111        2018-01-01 06:00:00     0

缺少的点2被替换为

17112        2018-01-01 02:00:00     0

我的主要问题是如何找到每个客户的最小和最大日期,然后生成日期间隔。

我尝试过按日期索引和重新采样,但没有帮助我找到解决方案。

另外,我想知道是否有一种方法可以直接查找上述模式中缺失值的客户 ID。我的数据非常大,@Vaishali 提供的解决方案计算量很大。任何输入都会有所帮助!

【问题讨论】:

  • 只是为了澄清,数据是否按每个客户的小时费率计算?当你说maxmin时,不应该是previous和next吗?从你的例子 1 中,对我来说最大是 2018-01-01 07:00:00 和最小 2018-01-01 00:00:00
  • 是的,数据预计按每个客户的小时费率计算。最大值和最小值不是上一个和下一个。

标签: python python-3.x pandas date datetime


【解决方案1】:

您可以按 custid 对数据框进行分组,并创建具有所需日期范围的索引。现在使用这个索引来重新索引数据

df['UsageDate'] = pd.to_datetime(df['UsageDate'])

idx = df.groupby('CustID')['UsageDate'].apply(lambda x: pd.Series(index = pd.date_range(x.min(), x.max(), freq = 'H'))).index

df.set_index(['CustID', 'UsageDate']).reindex(idx).fillna(0).reset_index().rename(columns = {'level_1':'UsageDate'})

    CustID  UsageDate               EnergyConsumed
0   17111   2018-01-01 00:00:00     1.095
1   17111   2018-01-01 01:00:00     1.129
2   17111   2018-01-01 02:00:00     1.165
3   17111   2018-01-01 03:00:00     1.833
4   17111   2018-01-01 04:00:00     1.697
5   17111   2018-01-01 05:00:00     1.835
6   17111   2018-01-01 06:00:00     0.000
7   17111   2018-01-01 07:00:00     1.835
8   17112   2018-01-01 00:00:00     1.095
9   17112   2018-01-01 01:00:00     1.129
10  17112   2018-01-01 02:00:00     0.000
11  17112   2018-01-01 03:00:00     1.833
12  17112   2018-01-01 04:00:00     1.697
13  17112   2018-01-01 05:00:00     1.835

说明:由于 Usagedates 必须是该 CustID 的最小和最大日期范围内的所有日期,因此我们按 CustID 对数据进行分组,并使用 date_range 创建一系列最小和最大日期。将日期设置为系列的索引而不是值。 groupby 的结果将是一个多索引,其 CUSTID 为 0 级,使用日期为 1 级。我们现在使用这个多索引来重新索引原始数据帧。它将使用索引匹配的值,其余部分分配 NaN。最后使用 fillna 将 NaN 转换为 0。

【讨论】:

  • 非常感谢!你能解释一下这些函数的工作原理吗?你是怎么想到的?
  • @rAmAnA,添加了解释。你也可以分解代码,逐段执行,看看每一步都发生了什么
  • 非常感谢。我想知道是否有一种方法可以直接找到上述模式中缺少值的客户 ID。我的数据非常大,这个操作计算量很大。任何输入都会有所帮助!
【解决方案2】:

先创建DatetimeIndex,然后在apply中使用asfreq

df['UsageDate'] = pd.to_datetime(df['UsageDate'])

df = (df.set_index('UsageDate')
        .groupby('CustID')['EnergyConsumed']
        .apply(lambda x: x.asfreq('H'))
        .fillna(0)
        .reset_index()
       )
print (df)
    CustID           UsageDate  EnergyConsumed
0    17111 2018-01-01 00:00:00           1.095
1    17111 2018-01-01 01:00:00           1.129
2    17111 2018-01-01 02:00:00           1.165
3    17111 2018-01-01 03:00:00           1.833
4    17111 2018-01-01 04:00:00           1.697
5    17111 2018-01-01 05:00:00           1.835
6    17111 2018-01-01 06:00:00           0.000
7    17111 2018-01-01 07:00:00           1.835
8    17112 2018-01-01 00:00:00           1.095
9    17112 2018-01-01 01:00:00           1.129
10   17112 2018-01-01 02:00:00           0.000
11   17112 2018-01-01 03:00:00           1.833
12   17112 2018-01-01 04:00:00           1.697
13   17112 2018-01-01 05:00:00           1.835

也可以使用参数ffillbfill

df = (df.set_index('UsageDate')
        .groupby('CustID')['EnergyConsumed']
        .apply(lambda x: x.asfreq('H', method='ffill'))
        .reset_index()
       )
print (df)
    CustID           UsageDate  EnergyConsumed
0    17111 2018-01-01 00:00:00           1.095
1    17111 2018-01-01 01:00:00           1.129
2    17111 2018-01-01 02:00:00           1.165
3    17111 2018-01-01 03:00:00           1.833
4    17111 2018-01-01 04:00:00           1.697
5    17111 2018-01-01 05:00:00           1.835
6    17111 2018-01-01 06:00:00           1.835
7    17111 2018-01-01 07:00:00           1.835
8    17112 2018-01-01 00:00:00           1.095
9    17112 2018-01-01 01:00:00           1.129
10   17112 2018-01-01 02:00:00           1.129
11   17112 2018-01-01 03:00:00           1.833
12   17112 2018-01-01 04:00:00           1.697
13   17112 2018-01-01 05:00:00           1.835

【讨论】:

    猜你喜欢
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多