【问题标题】:If a timestamp in one table is between two time stamps in another table, then increment by 1 using Python Pandas如果一个表中的时间戳介于另一个表中的两个时间戳之间,则使用 Python Pandas 递增 1
【发布时间】:2020-05-25 17:45:57
【问题描述】:

问题总结:

我想计算整个日历年中一天中任何给定分钟响应的救护车数量。 生成了两个 pandas 数据帧;第一个是救护车的紧急响应,显示紧急情况的开始时间戳和救护车紧急情况的结束时间戳。这些数据来自我们的数据库。例如,一辆救护车在 2020 年 1 月 1 日 00:30:17 对心脏骤停作出响应,而救护车在 2020 年 1 月 1 日 00:38:05.000 从该响应中清除。我们称这个数据框为“emergency_event”。

第二个 pandas 数据帧取 Emergency_event 的最小值和最大值。它使用最小和最大时间戳作为另一个数据帧的起点和终点来生成一个数据帧。它从起点到终点递增一分钟,并生成一个零作为工作卡车数量的占位符。让我们称这第二个数据帧为“巧合”,因为我们想计算在一分钟时间内同时工作的救护车的数量。

换句话说,第一个紧急事件从“2020-01-01 00:00:28”开始,因此“巧合”事件表将采用该值并增加一分钟,直到最后一个紧急事件结束时间戳。例如,“巧合”表如下所示:

calendar_timestamp      TrucksWorking

2020-01-01 00:00:28              0

2020-01-01 00:01:28              0

2020-01-01 00:02:28              0

2020-01-01 00:03:28              0

2020-01-01 00:04:28              0

2020-01-01 00:05:28              0

......

注意它是如何增加一分钟的,并且有一个占位符为零的救护车数量。

现在有两个数据框:“emergency_event”和“巧合”表。 该程序的目标是使用“重合”表的第一次观察并针对“紧急事件”表的每一行进行评估。 “重合”观察的时间戳是否出现在“emergency_events”的 StartTime 和 EndTime 之间?如果为真,则将 TrucksWorking 值增加 1。循环遍历每个“重合”观察并评估是否它位于任何“emergency_events”之间,如果为真则加 1。

在程序结束时,这将生成一个以一分钟为增量的数据帧以及当时工作的救护车数量。使用这些数据,我可以统计分析在任何给定时间工作的救护车数量,甚至可以按一天中的小时、工作日、白天/夜间等进行分析。这是非常强大的信息。

但我的逻辑卡住了,我需要你的帮助。具体来说,当时间戳在“emergency_events”表内时,我无法弄清楚如何让“巧合”表加 1。

我的尝试

for each in coincident.calendar_timestamp:
    if (coincident[coincident['calendar_timestamp']] >= emergency_events[emergency_events['StartTime']] & coincident[coincident['calendar_timestamp']] <= emergency_events[emergency_events['EndTime']]):
        coincident[coincident['TrucksWorking']] = coincident[coincident['TrucksWorking']] + 1
    else:
        coincident[coincident['TrucksWorking']]

我也尝试过:

# =============================================================================
# I have attempted the following
# the following code returns an error message
# ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
# =============================================================================
## for each in coincident.calendar_timestamp:
##     if (coincident[coincident['calendar_timestamp'].between(starting_point, ending_point)]):
##         coincident[coincident['TrucksWorking']] = coincident[coincident['TrucksWorking']] + 1
##     else:
##         coincident[coincident['TrucksWorking']]

# =============================================================================
# I have attempted the following
# a dead end code that I cannot make work
# df = coincident[coincident['calendar_timestamp'].between(starting_point, ending_point)]
# print(df.head(n = 5))
# =============================================================================

# =============================================================================
# I have attempted the following but it will not work
# another dead end code
# for timestamp in coincident_events.calendar:
#     print(coincident_events.calendar.query('coincident_events.calendar >= emergency_events.starting_point and coincident_events.calendar <= emergency_events.ending_point'))
# =============================================================================

显示我的代码:

# -*- coding: utf-8 -*-
# Python 3.7 Anaconda distribution
import pandas as pd
import datetime

# =============================================================================
# Step 1: Read in the ambulance runs with a starting and ending time values
# call this dataframe "emergency_events"
# =============================================================================

# the following array is a small sample when an ambulance starts a call and when it ends a call
data = [['2020-01-01 00:00:28.000','2020-01-01 00:35:28.987']
        , ['2020-01-01 00:02:34.000','2020-01-01 01:05:13.540']
        , ['2020-01-01 00:03:57.000','2020-01-01 01:14:44.537']
        , ['2020-01-01 00:06:17.000','2020-01-01 01:26:52.087']
        , ['2020-01-01 00:13:20.000','2020-01-01 01:17:31.310']
        , ['2020-01-01 00:14:01.000','2020-01-01 01:57:28.343']
        , ['2020-01-01 00:16:11.000','2020-01-01 00:39:34.967']
        , ['2020-01-01 00:22:03.000','2020-01-01 01:46:40.037']
        , ['2020-01-01 00:23:07.000','2020-01-01 00:49:25.890']
        , ['2020-01-01 00:23:19.000','2020-01-01 01:26:39.920']
        , ['2020-01-01 00:30:17.000','2020-01-01 00:38:05.000']] 

#convert the array to a pandas data frame
emergency_events = pd.DataFrame(data, columns = ['StartTime', 'EndTime'])

#convert the string values to date time values
emergency_events['StartTime'] = pd.to_datetime(emergency_events['StartTime'])
emergency_events['EndTime'] = pd.to_datetime(emergency_events['EndTime'])

# =============================================================================
# Step 2 Create a calendar of date time stamps incremented by 1 minute using the ambulance runs min/max values
# call this dataframe "coincident"
# =============================================================================

## establish a starting value based on the first ambulance event
starting_point = emergency_events.StartTime.min()
print(starting_point)
## establish an ending value based on the final ambulance call ending time.
ending_point = emergency_events.EndTime.max()
print(ending_point)
## create a range of time stamps incremented by 1 minute from starting point to ending point
days = pd.date_range(starting_point, ending_point, freq='min')

## create a pandas dataframe with two columns: calendar for time stamps and a place holder of 0 for trucks working 
coincident = pd.DataFrame({'calendar_timestamp': days, 'TrucksWorking': 0})
## print it out to verify the data
print(coincident.head(n = 5))

# =============================================================================
# Step 3 --- now for the difficult part
# if a "coincident" time stamp is between a start and end time of an emergency_event
# increment the TrucksWorking column by 1
# loop through every "coincident" observation and test if it is between a start and an end of an "emergency_event"
# =============================================================================
for each in coincident.calendar_timestamp:
    if (coincident[coincident['calendar_timestamp']] >= emergency_events[emergency_events['StartTime']] & coincident[coincident['calendar_timestamp']] <= emergency_events[emergency_events['EndTime']]):
        coincident[coincident['TrucksWorking']] = coincident[coincident['TrucksWorking']] + 1
    else:
        coincident[coincident['TrucksWorking']]

## at the end of this program it should return a calendar of date time stamps with 
## the number of ambulances at work during that one minute interval.
## this information can be used for data modeling.

# =============================================================================
# I have attempted the following
# the following code returns an error message
# ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
# =============================================================================
## for each in coincident.calendar_timestamp:
##     if (coincident[coincident['calendar_timestamp'].between(starting_point, ending_point)]):
##         coincident[coincident['TrucksWorking']] = coincident[coincident['TrucksWorking']] + 1
##     else:
##         coincident[coincident['TrucksWorking']]

# =============================================================================
# I have attempted the following
# a dead end code that I cannot make work
# df = coincident[coincident['calendar_timestamp'].between(starting_point, ending_point)]
# print(df.head(n = 5))
# =============================================================================

# =============================================================================
# I have attempted the following but it will not work
# another dead end code
# for timestamp in coincident_events.calendar:
#     print(coincident_events.calendar.query('coincident_events.calendar >= emergency_events.starting_point and coincident_events.calendar <= emergency_events.ending_point'))
# =============================================================================

print(coincident.head(n = 20))

# =============================================================================
# Step 4: verify the "coincident" table is correct and then analyze the data
# Printing the "coincident" dataframe should look something like:
# =============================================================================
#     StartTime                       TrucksWorking    
# 0  2020-01-01 00:00:28              1
# 1  2020-01-01 00:01:28              1
# 2  2020-01-01 00:02:28              1
# 3  2020-01-01 00:03:28              1
# 4  2020-01-01 00:04:28              2
# 5  2020-01-01 00:05:28              2
# 6  2020-01-01 00:06:28              3
# 7  2020-01-01 00:07:28              3
# 8  2020-01-01 00:08:28              3
# 9  2020-01-01 00:09:28              3
# 10 2020-01-01 00:10:28              3
# etc for a full calendar year of ambulance responses

# =============================================================================
# Step 5: analyze the data looking for patterns of ambulance utilization. TBD
# =============================================================================

【问题讨论】:

  • 我对您的理解是否正确:您想计算整个日历年中一天中任何给定分钟响应的#number of ambulances?
  • 是的,mozart_kv467,我想计算正在响应的救护车的数量,并且我希望在日历年的每一分钟都进行此计算。例如,2020 年 6 月 1 日 12:00:00 有 11 辆救护车正在呼叫。然后在 12:01:00 派出了另一辆救护车,所以现在有 12 辆救护车正在呼叫。这些数据将使我能够分析紧急服务中的模式。

标签: python pandas dataframe datetime increment


【解决方案1】:

使用您的数据,我找到了以下解决方案。我只使用了2020 年的前 200 分钟,但您可以通过将 periods=200 调整为每年的分钟数来轻松更改。

我使用了以下 variablesdf 对应于您的重合数据框。从 2020 年 1 月 1 日起,我每分钟都预先生成它:

import pandas as pd
import datetime
df = pd.DataFrame()
df['time1'] = pd.date_range('2020-01-01 00:00:00', periods=200, freq='min')
df['trucks working'] = 0
print(df)

这给了我一年中所有卡车都在工作的分钟= 0

                  time1  trucks working
0   2020-01-01 00:00:00               0
1   2020-01-01 00:01:00               0
2   2020-01-01 00:02:00               0
3   2020-01-01 00:03:00               0
4   2020-01-01 00:04:00               0
..                  ...             ...
195 2020-01-01 03:15:00               0
196 2020-01-01 03:16:00               0
197 2020-01-01 03:17:00               0
198 2020-01-01 03:18:00               0
199 2020-01-01 03:19:00               0

使用您的紧急呼叫作为data

data = [['2020-01-01 00:00:28.000','2020-01-01 00:35:28.987']
    , ['2020-01-01 00:02:34.000','2020-01-01 01:05:13.540']
    , ['2020-01-01 00:03:57.000','2020-01-01 01:14:44.537']
    , ['2020-01-01 00:06:17.000','2020-01-01 01:26:52.087']
    , ['2020-01-01 00:13:20.000','2020-01-01 01:17:31.310']
    , ['2020-01-01 00:14:01.000','2020-01-01 01:57:28.343']
    , ['2020-01-01 00:16:11.000','2020-01-01 00:39:34.967']
    , ['2020-01-01 00:22:03.000','2020-01-01 01:46:40.037']
    , ['2020-01-01 00:23:07.000','2020-01-01 00:49:25.890']
    , ['2020-01-01 00:23:19.000','2020-01-01 01:26:39.920']
    , ['2020-01-01 00:30:17.000','2020-01-01 00:38:05.000']] 

我添加列名称并将生成的数据框命名为emergency_events

 emergency_events = pd.DataFrame(data, columns = ['StartTime', 'EndTime'])

现在我可以遍历数据框emergency_events

并增加'trucks working' 对于一天中的每一分钟 在'StartTime''EndTime' 的一行之间

for index2, row2 in df.iterrows():
for index, row in emergency_events.iterrows():
    if pd.to_datetime(row['StartTime']) <= pd.to_datetime(row2['time1']) <= pd.to_datetime(row['EndTime']):
        #print(row2['trucks working'])
        #print(row['StartTime'],row2['time1'],row['EndTime'])
        df.at[index2,'trucks working'] += 1

这给了我一个数据框,其中包含一天中每分钟的卡车数量。

time1  trucks working
0   2020-01-01 00:00:00               0
1   2020-01-01 00:01:00               1
2   2020-01-01 00:02:00               1
3   2020-01-01 00:03:00               2
4   2020-01-01 00:04:00               3
..                  ...             ...
195 2020-01-01 03:15:00               0
196 2020-01-01 03:16:00               0
197 2020-01-01 03:17:00               0
198 2020-01-01 03:18:00               0
199 2020-01-01 03:19:00               0

【讨论】:

  • 非常感谢您的周到回复。效果很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多