【问题标题】:Pandas use start/end datetimes to find concurrent phone callsPandas 使用开始/结束日期时间来查找并发电话
【发布时间】:2022-11-15 10:05:14
【问题描述】:

我有一组带有连接/断开时间的电话记录,我想找出数据中时间段内每一秒的并发通话数。然后我想使用该并发呼叫数据来获取白天的高峰呼叫时间。

我有一个工作示例,但是在一周的数据中以 1 秒的时间增量进行迭代需要永远。

示例数据框:

df
      dateTimeConnect  dateTimeDisconnect
0 2020-11-07 08:01:02 2020-11-07 08:02:39
1 2020-11-07 08:01:19 2020-11-07 08:02:08
2 2020-11-07 08:01:44 2020-11-07 08:02:05
3 2020-11-07 08:02:10 2020-11-07 08:03:30
4 2020-11-07 08:03:01 2020-11-07 08:04:15

[5 rows x 2 columns]

获取最小和最大时间:

startTime = df.dateTimeConnect.min()
loopTime = df.dateTimeConnect.min()
endTime = df.dateTimeDisconnect.max()
totalTime = df.dateTimeDisconnect.max() - df.dateTimeConnect.min()

print(f"{startTime=}")
print(f"{endTime=}")

startTime=Timestamp('2020-11-07 08:01:02')
endTime=Timestamp('2022-11-07 08:04:15')

当 loopTime 小于 endTime 时循环,创建带有 loc 掩码的新数据帧以在那一秒获得并发调用,将 loopTime 增加 1 秒。

callsdf = pd.DataFrame()

while loopTime <= endTime:
    concurrent_calls = df.loc[(df['dateTimeConnect'] <= loopTime) & (df['dateTimeDisconnect'] > loopTime)].shape[0]
    print(f"{loopTime}", f"{concurrent_calls=}")
    callsdf = pd.concat([callsdf, pd.Series({"datetime": loopTime, "concurrent_calls": concurrent_calls}).to_frame().T])
    loopTime += timedelta(seconds=1)

结果数据框:

               datetime concurrent_calls
0   2020-11-07 08:01:02                1
1   2020-11-07 08:01:03                1
2   2020-11-07 08:01:04                2
3   2020-11-07 08:01:05                2
4   2020-11-07 08:01:06                3
..                  ...              ...
189 2020-11-07 08:04:11                1
190 2020-11-07 08:04:12                1
191 2020-11-07 08:04:13                1
192 2020-11-07 08:04:14                1
193 2020-11-07 08:04:15                0

有没有一种更有效的方法可以用熊猫来完成?

【问题讨论】:

  • 这回答了你的问题了吗? How to count overlapping datetime intervals in Pandas?
  • 进一步添加评论,然后我认为您可以获得最大并发值,跟踪它的索引,并且可以获得最并发时间范围的开始(索引)和结束日期时间(索引+ 1)

标签: python pandas datetime


【解决方案1】:

使用链接的方法,然后做asfreq~

out = (df.melt(var_name='status',value_name='time')
   .sort_values('time')
   .assign(counter=lambda x: x.status.map({'dateTimeConnect': 1, 'dateTimeDisconnect': -1}).cumsum())
   .set_index('time')
   .asfreq('s', 'pad'))

print(out)

输出:

                                 status  counter
time
2020-11-07 08:01:02     dateTimeConnect        1
2020-11-07 08:01:03     dateTimeConnect        1
2020-11-07 08:01:04     dateTimeConnect        1
2020-11-07 08:01:05     dateTimeConnect        1
2020-11-07 08:01:06     dateTimeConnect        1
...                                 ...      ...
2020-11-07 08:04:11  dateTimeDisconnect        1
2020-11-07 08:04:12  dateTimeDisconnect        1
2020-11-07 08:04:13  dateTimeDisconnect        1
2020-11-07 08:04:14  dateTimeDisconnect        1
2020-11-07 08:04:15  dateTimeDisconnect        0

[194 rows x 2 columns]

【讨论】:

    【解决方案2】:

    使用麻木。

    times_array = np.array(times, dtype='datetime64[s]')
    
    
    def count_active_users(times, time):
        return np.count_nonzero((times[:, 0] <= time) & (times[:, 1] > time))
    
    
    check = pd.Timestamp("2020-11-07 08:02:00")
    r = count_active_users(times_array, check)
    

    使用任意测试,您的代码需要 33 秒才能运行; numpy 占用了 0.2。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多