这是我要提高代码性能的棘手问题。想象这样一个数据框:
TOUR_ID ID PAGE_ID CREATED DATE AVAILABILITY
T_1 ID1 P1 2018-07-03 19:10:19 AVAILABLE
T_1 ID1 P1 2018-07-03 19:10:20 AVAILABLE
T_1 ID1 P2 2018-07-03 19:12:33 AVAILABLE
T_1 ID2 P3 2018-07-03 19:13:34 AVAILABLE
T_1 ID2 P3 2018-07-03 19:13:35 NOT AVAILABLE
T_1 ID2 P4 2018-07-03 19:16:24 AVAILABLE
T_2 ID3 P4 2018-07-03 18:23:19 AVAILABLE
T_2 ID3 P4 2018-07-03 18:23:20 NOT AVAILABLE
T_2 ID1 P1 2018-07-03 19:10:21 NOT AVAILABLE
T_2 ID2 P3 2018-07-03 19:13:37 NOT AVAILABLE
T_2 ID2 P3 2018-07-03 19:13:38 NOT AVAILABLE
T_2 ID3 P5 2018-07-03 20:56:33 AVAILABLE
T_2 ID3 P5 2018-07-03 20:56:34 NOT AVAILABLE
T_2 ID3 P5 2018-07-03 22:56:35 AVAILABLE
T_2 ID3 P6 2018-07-03 22:57:20 NOT AVAILABLE
T_2 ID3 P7 2018-07-03 22:58:35 AVAILABLE
T_2 ID4 P8 2018-07-03 22:59:00 AVAILABLE
T_2 ID1 P1 2018-07-03 23:12:00 AVAILABLE
T_2 ID1 P3 2018-07-03 23:32:00 AVAILABLE
在每个组(Tour_ID,ID,Page_ID)上,我需要使用上一个组的最后一个值创建一列。另外,在第一次对tour_ID或ID进行更改时,我将获得NaN,因为该组合没有任何先前的值。
结果应如下所示:
TOUR_ID ID PAGE_ID CREATED DATE AVAILABILITY PREVIOUS AVAILABILITY
T_1 ID1 P1 2018-07-03 19:10:19 AVAILABLE NaN
T_1 ID1 P1 2018-07-03 19:10:20 AVAILABLE NaN
T_1 ID1 P2 2018-07-03 19:12:33 AVAILABLE AVAILABLE
T_1 ID2 P3 2018-07-03 19:13:34 AVAILABLE NaN
T_1 ID2 P3 2018-07-03 19:13:35 NOT_AVAILABLE NaN
T_1 ID2 P4 2018-07-03 19:16:24 AVAILABLE NOT_AVAILABLE
T_2 ID3 P4 2018-07-03 18:23:19 AVAILABLE NaN
T_2 ID3 P4 2018-07-03 18:23:20 NOT AVAILABLE NaN
T_2 ID1 P1 2018-07-03 19:10:21 NOT AVAILABLE NaN
T_2 ID2 P3 2018-07-03 19:13:37 NOT AVAILABLE NaN
T_2 ID2 P3 2018-07-03 19:13:38 NOT AVAILABLE NaN
T_2 ID3 P5 2018-07-03 20:56:33 AVAILABLE NOT AVAILABLE
T_2 ID3 P5 2018-07-03 20:56:34 NOT AVAILABLE NOT AVAILABLE
T_2 ID3 P5 2018-07-03 22:56:35 AVAILABLE NOT AVAILABLE
T_2 ID3 P6 2018-07-03 22:57:20 NOT AVAILABLE AVAILABLE
T_2 ID3 P7 2018-07-03 22:58:35 AVAILABLE NOT AVAILABLE
T_2 ID4 P8 2018-07-03 22:59:00 AVAILABLE NaN
T_2 ID1 P1 2018-07-03 23:12:00 AVAILABLE NaN
T_2 ID1 P3 2018-07-03 23:32:00 AVAILABLE AVAILABLE
我有一个可以运行的代码,但是它伸缩性不好(数据帧大约有900,000行)。对于改善代码性能的任何帮助,将不胜感激。
这是我到目前为止所拥有的:
for current_op in df.TOUR_ID.unique():
dummy = df[df.TOUR_ID == current_op].ID.unique()
for current_ID in dummy:
dummy_m = df[(df.TOUR_ID == current_op) & (df.ID == current_ID)].PAGE_ID.unique()
for current_page in dummy_m:
mask = (df.TOUR_ID == current_op) & (df.ID == current_ID) & (df.PAGE_ID == current_page)
indexes = mask.reset_index().rename(columns ={0:'Bool'})
ind = indexes.index[indexes['Bool'] == True].tolist()[0]
if (ind == 0) | ((current_page == dummy_m[0])):
df.loc[mask,'Previous_availability'] = np.nan
else:
previous_aval = df.AVAILABILITY.loc[indexes['index'].loc[ind-1]]
df.loc[mask, 'Previous_availability'] = previous_aval
注意:NaN最终将被丢弃
-编辑
下面是创建数据框的代码:
import pandas as pd
import numpy as np
df = pd.DataFrame([['T_1','ID1','P1','2018-07-03 19:10:19', 'AVAILABLE'],
['T_1','ID1','P1','2018-07-03 19:10:20', 'AVAILABLE'],
['T_1','ID1','P2','2018-07-03 19:12:33', 'AVAILABLE'],
['T_1','ID2','P3','2018-07-03 19:13:34', 'AVAILABLE'],
['T_1','ID2','P3','2018-07-03 19:13:35', 'NOT AVAILABLE'],
['T_1','ID2','P4','2018-07-03 19:16:24', 'AVAILABLE'],
['T_2','ID3','P4','2018-07-03 18:23:19', 'AVAILABLE'],
['T_2','ID3','P4','2018-07-03 18:23:20', 'NOT AVAILABLE'],
['T_2','ID1','P1','2018-07-03 19:10:21', 'NOT AVAILABLE'],
['T_2','ID2','P3','2018-07-03 19:13:36', 'NOT AVAILABLE'],
['T_2','ID2','P3','2018-07-03 19:13:37', 'NOT AVAILABLE'],
['T_2','ID3','P5','2018-07-03 20:56:33', 'AVAILABLE'],
['T_2','ID3','P5','2018-07-03 20:56:34', 'NOT AVAILABLE'],
['T_2','ID3','P5','2018-07-03 22:56:35', 'AVAILABLE'],
['T_2','ID3','P6','2018-07-03 22:57:20', 'NOT AVAILABLE'],
['T_2','ID3','P7','2018-07-03 22:58:35', 'AVAILABLE'],
['T_2','ID4','P8','2018-07-03 22:59:00', 'AVAILABLE'],
['T_2','ID1','P1','2018-07-03 23:12:00', 'AVAILABLE'],
['T_2','ID1','P3','2018-07-03 23:32:00', 'AVAILABLE']
], columns=['TOUR_ID','ID','PAGE_ID','CREATED DATE', 'AVAILABILITY'])
答案 0 :(得分:1)
那真是个大难题,但这是解决这个问题的一种方法:
df = pd.read_csv('test.tsv').set_index(['TOUR_ID', 'ID', 'PAGE_ID'])
获取每组的最后一行,向前移动一位:
shifted = df.groupby(['TOUR_ID', 'ID', 'PAGE_ID']).last().shift(1).reset_index()
现在,我们对在PAGE_ID
中看到变化但在ID
中看不到变化的行感兴趣,因此我们构造了一个布尔掩码:
change = shifted != shifted.shift(1)
mask = np.array(change.PAGE_ID & ~change.ID & ~change.TOUR_ID)
最后,我们应用遮罩并加入以创建新列:
shifted.set_index(['TOUR_ID', 'ID', 'PAGE_ID'], inplace=True)
shifted[~mask] = np.nan
result = df.join(shifted['AVAILABILITY'], rsuffix='LAST')
答案 1 :(得分:0)
好,这是我的刺路。
1)创建助手系列P_INT
(PAGE_ID
的整数部分)
2)使用MultiIndex df_last_availability
创建助手DataFrame ['TOUR_ID', 'ID', 'P_INT']
3)将P_INT
偏移1
4)重置原始df的索引,使其与df_last_availability
相匹配。从这里,您可以轻松地(使用左联接)合并索引上的2个数据框。
5)最后一种链接方法只是清除操作,以将数据帧恢复为其原始形状-即删除辅助字段并将索引重置为原始值。
df['P_INT'] = df.PAGE_ID.str.extract('(\d+)').astype(int)
df_last_availability = df.groupby(['TOUR_ID', 'ID', 'P_INT']).last()
df['P_INT'] = df.P_INT - 1
(df.set_index(['TOUR_ID', 'ID', 'P_INT'])
.merge(df_last_availability[['AVAILABILITY']], how='left',
left_index=True, right_index=True, suffixes=('', '_PREV'))
.reset_index()
.drop(['P_INT'], axis=1))