我在数据库中有一系列电子邮件,它们被分成多个线程,因此下面的数据框将表示一个对话。我正在尝试计算我以及响应者的平均响应时间。
目前,我正在通过循环执行此操作,这似乎效率很低。有没有可用的可用功能?我是否有可能找到一种方法,仅过滤出唯一的回复?这样我就可以改变时间并以这种方式计算差异。
样本数据框。如下所示,响应之前,可能有1个参与者发送多封电子邮件。仅应使用第一个来计算响应时间差
Sender DateTime
Me ISO8601
Me ISO8601
Customer ISO8601
Me ISO8601
Customer ISO8601
Customer ISO8601
Me ISO8601
Me ISO8601
Me ISO8601
Customer ISO8601
当前操作的伪代码(太长,无法放入完整的实际代码)
# Track who responded last
last_comment_type = None
# Track response numbers (number of times each party responded)
customer_response_count = 0
my_response_count = 0
# Determine who the first sender is (doesn't always have to be me)
if df.ix[df.index.values.min()]['ResponseType'] == customer:
last_comment_type = 'Customer'
next_response = df.iloc[1:][df['ResponseType'] = 'Me']
my_total_response_time += next_response - row
my_response_count += 1
else:
last_comment_type = 'Me'
next_response = df.iloc[1:][df['ResponseType'] = 'Customer']
customer_total_response_time += next_response - row
customer_response_count += 1
# Loop over rest of rows and figure out who responded to who.
for row in df.itertuples():
if row.ResponseType == 'Customer' and last_comment_type == 'Me':
next_response = df[df.index > row.Index][df['ResponseType'] != 'Customer']
my_total_response_time += next_response - row
my_response_count += 1
if row.ResponseType == 'Me' and last_comment_type == 'Customer':
next_response = df[df.index > row.Index][df['ResponseType'] != 'Me']
customer_total_response_time += next_response - row
customer_response_count += 1
my_response_avg = my_total_response_time/my_response_count
customer_response_avg = customer_total_response_time/customer_response_count
答案 0 :(得分:1)
如果我理解正确,Pandas可以更简单地完成此操作。如果您只想计算前几条消息之间的差异:
df['block'] = ((df.Sender != df.Sender.shift()).cumsum())
mean_response_time = df.drop_duplicates('block', keep='first')['DateTime'].diff().mean()
如果要通过Sender
计算平均响应时间,可以使用groupby()
:
df['response_time'] = df.drop_duplicates('block', keep='first')['DateTime'].diff()
gr = df.groupby('Sender').response_time
mean_response_times = gr.sum() / gr.count()
注意:由于this issue与groupby
和mean()
一起使用,所以我使用总和/计数而不是平均值, >
让我们分解一下。首先,我们需要一个具有可用时间的示例数据帧(这是我建议您在类似问题中提供的数据):
times = pd.date_range('10/18/2018', periods=8, freq='H')
df = pd.DataFrame({'Sender': ['A','B','A','A','B','B','B','A'], 'DateTime': times})
这为您提供了这样的数据框:
DateTime Sender
0 2018-10-18 00:00:00 A
1 2018-10-18 01:00:00 B
2 2018-10-18 02:00:00 A
3 2018-10-18 03:00:00 A
4 2018-10-18 04:00:00 B
5 2018-10-18 05:00:00 B
6 2018-10-18 06:00:00 B
7 2018-10-18 07:00:00 A
df['block'] = ((df.Sender != df.Sender.shift()).cumsum())
创建一个新列,其中来自同一Sender
的连续行具有相同的编号:
DateTime Sender block
0 2018-10-18 00:00:00 A 1
1 2018-10-18 01:00:00 B 2
2 2018-10-18 02:00:00 A 3
3 2018-10-18 03:00:00 A 3
4 2018-10-18 04:00:00 B 4
5 2018-10-18 05:00:00 B 4
6 2018-10-18 06:00:00 B 4
7 2018-10-18 07:00:00 A 5
由于我们关心的(在版本1中)是从一个Sender
发送第一条消息到下一个发件人发送第一条消息之间的时间,因此我们可以删除所有具有block
的重复值:
df.drop_duplicates('block', keep='first')['DateTime']
这为我们提供了每个Sender
特定块中每个第一条消息的时间:
0 2018-10-18 00:00:00
1 2018-10-18 01:00:00
2 2018-10-18 02:00:00
4 2018-10-18 04:00:00
7 2018-10-18 07:00:00
如果我们想要所有发件人的平均时间,我们要做的就是添加diff()
和mean()
以获得行之间的平均时间:
df.drop_duplicates('block', keep='first')['DateTime'].diff().mean()
哪个给:
Timedelta('0 days 01:45:00')
如果我们想获取发件人的平均时间 ,则需要采取额外的步骤。我们为响应时间创建了一个新列,然后将其按发件人分组,然后计算平均值。
df['response_time'] = df.drop_duplicates('block', keep='first')['DateTime'].diff()
gr = df.groupby('Sender').response_time
mean_response_time = gr.sum() / gr.count()
结果是:
Sender
A 02:00:00
B 01:30:00
注意:如果要计算一个发件人的最后一封邮件与下一个发件人的第一封邮件之间的差额:
df['block'] = ((df.Sender != df.Sender.shift()).cumsum())
df['last_message'] = df.drop_duplicates('block', keep='last')['DateTime']
df['first_message'] = df.drop_duplicates('block', keep='first')['DateTime'].shift(-1)
mean_response_time = (df['first_message'].shift(-1) - df['last_message']).mean()