簡體   English   中英

用最后一組的最后一個值填充組列

[英]Fill group column with last value of the last group

這是一個棘手的問題,我希望提高代碼性能。 想象一個像這樣的數據框:

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'])

這是一個相當令人頭疼的問題,但這是解決這個問題的一種方法:

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) 創建助手系列P_INT ( PAGE_ID整數部分)

2) 使用 MultiIndex ['TOUR_ID', 'ID', 'P_INT']創建輔助 DataFrame df_last_availability

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))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM