pandas 查找子 Dataframe 的索引并在主 Dataframe 中匹配

blmhpbnm  于 2023-03-16  发布在  其他
关注(0)|答案(2)|浏览(107)

我有一个 Dataframe 如下:
| 调用ID|保存日期|关闭日期|时间增量|
| - ------|- ------|- ------|- ------|
| 1个|2023年2月8日14时35分09秒|2023年2月8日14时35分56秒||
| 1个|2023年2月8日14时35分56秒|2023年2月8日14时42分|价值|
| 第二章|2023年2月7日10时17分18秒|2023年2月7日10时22分23秒||
| 第二章|2023年2月7日10时22分23秒|2023年2月7日15:09:14||
| 第二章|2023年2月7日15:09:14|2023年2月7日16时20分50秒||
| 第二章|2023年2月7日16时20分49秒|2023年2月8日09时23分16秒||
| 第二章|2023年2月8日09时23分16秒|2023年2月8日09:27:21|价值|
| 三个|2023年3月10日10时31分25秒|2023年3月10日10时41分37秒||
| 三个|2023年3月10日10时41分37秒|2023年3月10日14时23分18秒|价值|
为了实现时间增量,我正在执行以下操作:

delta_time = a.iloc[-1]['CloseDate'] - a.iloc[0]['StorageDate']

我需要从每个CallID的第一个StorageDate中减去最后一个CloseDate(总共16821),并且delta_time必须位于每个CallID的最后一行,其中有值(与我从中获取CloseDate的值相同)。
我的做法如下:

callid = 1
while callid <= 16821:
    df1 = df1[df1['CallID'] == callid]
    delta_time = df1.iloc[-1]['CloseDate'] - df1.iloc[0]['StorageDate']
    callid += 1

但问题是我无法将delta_time值解析到正确的行。
在我尝试使用loc和iloc之前,我设法使用以下结构将其发送到df 1中的正确行:

delta_time = df1.iloc[-1]['CloseDate'] - df1.iloc[0]['StorageDate']
 df1.loc[1, 'Time Delta'] = delta_time

它可以工作,但效率不高,因为我必须为每个不同的CallID更改loc中的值,而iloc[-1]似乎不起作用。此外,我不知道如何将其解析到主 Dataframe ,而不仅仅是我创建来进行计算的 Dataframe 。
有人能帮帮我吗?

qxgroojn

qxgroojn1#

使用groupby.transformwhere

df[['StorageDate', 'CloseDate']] = df[['StorageDate', 'CloseDate']].apply(pd.to_datetime)

g = df.groupby('CallID')

df['Time Delta'] = (g['CloseDate'].transform('last')
                    .sub(g['StorageDate'].transform('first'))
                    .where(~df['CallID'].duplicated(keep='last'))
                   )

输出:

CallID         StorageDate           CloseDate      Time Delta
0       1 2023-02-08 14:35:09 2023-02-08 14:35:56             NaT
1       1 2023-02-08 14:35:56 2023-02-08 14:42:00 0 days 00:06:51
2       2 2023-02-07 10:17:18 2023-02-07 10:22:23             NaT
3       2 2023-02-07 10:22:23 2023-02-07 15:09:14             NaT
4       2 2023-02-07 15:09:14 2023-02-07 16:20:50             NaT
5       2 2023-02-07 16:20:49 2023-02-08 09:23:16             NaT
6       2 2023-02-08 09:23:16 2023-02-08 09:27:21 0 days 23:10:03
7       3 2023-03-10 10:31:25 2023-03-10 10:41:37             NaT
8       3 2023-03-10 10:41:37 2023-03-10 14:23:18 0 days 03:51:53

可重现输入:

df = pd.DataFrame({'CallID': [1, 1, 2, 2, 2, 2, 2, 3, 3],
                   'StorageDate': ['2023-02-08 14:35:09', '2023-02-08 14:35:56', '2023-02-07 10:17:18', '2023-02-07 10:22:23', '2023-02-07 15:09:14', '2023-02-07 16:20:49', '2023-02-08 09:23:16', '2023-03-10 10:31:25', '2023-03-10 10:41:37'],
                   'CloseDate': ['2023-02-08 14:35:56', '2023-02-08 14:42:00', '2023-02-07 10:22:23', '2023-02-07 15:09:14', '2023-02-07 16:20:50', '2023-02-08 09:23:16', '2023-02-08 09:27:21', '2023-03-10 10:41:37', '2023-03-10 14:23:18']})

df[['StorageDate', 'CloseDate']] = df[['StorageDate', 'CloseDate']].apply(pd.to_datetime)
hi3rlvi2

hi3rlvi22#

使用Series.duplicated筛选由GroupBy.transform生成的最后几行:

m = ~df['CallID'].duplicated(keep='last')

g = df.groupby('CallID')

df.loc[m, 'Time Delta'] = (g['CloseDate'].transform('last')[m]
                                         .sub(g['StorageDate'].transform('first')[m]))
print (df)
   CallID         StorageDate           CloseDate       Time Delta
0       1 2023-02-08 14:35:09 2023-02-08 14:35:56              NaN
1       1 2023-02-08 14:35:56 2023-02-08 14:42:00  0 days 00:06:51
2       2 2023-02-07 10:17:18 2023-02-07 10:22:23              NaN
3       2 2023-02-07 10:22:23 2023-02-07 15:09:14              NaN
4       2 2023-02-07 15:09:14 2023-02-07 16:20:50              NaN
5       2 2023-02-07 16:20:49 2023-02-08 09:23:16              NaN
6       2 2023-02-08 09:23:16 2023-02-08 09:27:21  0 days 23:10:03
7       3 2023-03-10 10:31:25 2023-03-10 10:41:37              NaN
8       3 2023-03-10 10:41:37 2023-03-10 14:23:18  0 days 03:51:53

另一个通过GroupBy.agg聚合的解决方案,Map差异为:

def f(x):
    ts = x.total_seconds()
    hours, remainder = divmod(ts, 3600)
    minutes, seconds = divmod(remainder, 60)
    return ('{:02d}:{:02d}:{:02d}').format(int(hours), int(minutes), int(seconds))

m = ~df['CallID'].duplicated(keep='last')

df1 = df.groupby('CallID').agg({'CloseDate':'last', 'StorageDate':'first'})

df.loc[m, 'Time Delta'] = (df.loc[m, 'CallID'].map(df1['CloseDate'].sub(df1['StorageDate']))
                             .apply(f))
print (df)
   CallID         StorageDate           CloseDate Time Delta
0       1 2023-02-08 14:35:09 2023-02-08 14:35:56        NaN
1       1 2023-02-08 14:35:56 2023-02-08 14:42:00   00:06:51
2       2 2023-02-07 10:17:18 2023-02-07 10:22:23        NaN
3       2 2023-02-07 10:22:23 2023-02-07 15:09:14        NaN
4       2 2023-02-07 15:09:14 2023-02-07 16:20:50        NaN
5       2 2023-02-07 16:20:49 2023-02-08 09:23:16        NaN
6       2 2023-02-08 09:23:16 2023-02-08 09:27:21   23:10:03
7       3 2023-03-10 10:31:25 2023-03-10 10:41:37        NaN
8       3 2023-03-10 10:41:37 2023-03-10 14:23:18   03:51:53

相关问题