1、需求:
假設(shè)有一個用戶產(chǎn)品購買記錄名單,我們想整理出用戶購買訂單的前一個訂單的信息,形成表格。示例如下:


如圖所示,實際上就是將1001訂單的信息增加幾列放到1002后面。
字段解釋:
user_id:用戶id
order_id:訂單號
oder_time:購買時間
product_type:商品類型
amount:商品金額
buy_times:第幾次購買
pre后綴:表示前一個訂單的相關(guān)信息
2、思路和解決方法1:
思路:
以原始思維的角度,實現(xiàn)最終效果有以下步驟:
1、選取每一個用戶的所有記錄
2、對用戶購買次數(shù)排序,產(chǎn)生新列buy_times
3、對每一條購買記錄進行整理,如果是該用戶的第一條記錄,則pre列為空;如果非第一條記錄,則在pre列增加前一條數(shù)據(jù)記錄
4、合并整理好的數(shù)據(jù)
5、輸出結(jié)果
Python3代碼:
%python 3
import pandas as pd
#思路1
#讀取數(shù)據(jù)
ini_df=pd.read_excel('file:///D:/Python/170818購買產(chǎn)品前后關(guān)系.xlsx',
sheetname='模擬數(shù)據(jù)')
#獲取不重復(fù)的user_id,以便進行遍歷
dist_id=ini_df['user_id'].drop_duplicates()
#直接提取大于1和等于1次的用戶
freq=ini_df['user_id'].value_counts().reset_index()
onetime_user=freq[freq['user_id']==1]['index']
multtime_user=freq[freq['user_id']>1]['index']
#循環(huán)處理用戶第二個及以上訂單
#定義最終數(shù)據(jù)
final_data=pd.DataFrame()
for user_id in multtime_user:
#篩選user_id對應(yīng)的訂單信息
mid_data=ini_df[ini_df['user_id']==user_id]
print(user_id)
#刪除原索引以方便后期對索引進行操作
mid_data=mid_data.reset_index(drop=True)
for i in range(len(mid_data)-1):
#獲取當(dāng)前訂單信息
each_data_a=mid_data.iloc[[i]].reset_index(drop=True)
#獲取前一個訂單信息
each_data_b=mid_data.iloc[[i+1]].reset_index(drop=True)
#將前一個訂單信息合并到當(dāng)前訂單中
each_data=pd.merge(each_data_a,each_data_b,left_index=True,right_index=True,suffixes=('_pre',''))
#將新的數(shù)據(jù)添加到最終數(shù)據(jù)中
final_data=final_data.append(each_data)
#篩選用戶第一個訂單,并進行數(shù)據(jù)合并
first_order=ini_df.drop_duplicates('user_id')
final_data=final_data.append(first_order)
#對數(shù)據(jù)增加購買次數(shù)和對列排序
#重設(shè)index后才能進行分組排序
final_data.reset_index(drop=True,inplace=True)
final_data['buy_times']=final_data['order_time'].groupby(final_data['user_id']).rank()
#整理結(jié)果,去掉不需要的列,并對列排序
final_data=final_data[['user_id', 'buy_times', 'order_id', 'order_time', 'product_type','amount',
'order_id_pre', 'order_time_pre', 'product_type_pre', 'amount_pre']]
#對行排序,恢復(fù)初始數(shù)據(jù)繡工
final_data.sort_values(by=['user_id','order_time'],inplace=True)
final_data.reset_index(drop=True,inplace=True)
#存儲數(shù)據(jù)
final_data.to_csv('結(jié)果.csv')

2、思路和解決方法2:
上述方法很符合人的基本思維,快速思考出結(jié)果,但是程序繁瑣,運行效率很低。
仔細觀察數(shù)據(jù)結(jié)構(gòu),其實我們發(fā)現(xiàn)對每一個用戶,只需要對其購買的第n+1個產(chǎn)品,后面加上第n個產(chǎn)品的信息就可以了。
于是,可以利用pandas的DataFrame的特性,復(fù)制相同的一個DataFrame,使用merge方法,將兩個DataFrame合并即可。合并的連接方式,即通過user_id相等,left.buy_times=right.buy_times-1。
Python3代碼:
%python 3
import pandas as pd
#思路2
#讀取數(shù)據(jù)
ini_df=pd.read_excel('file:///D:/Python/170818購買產(chǎn)品前后關(guān)系.xlsx',
sheetname='模擬數(shù)據(jù)')
#添加每個用戶的購買次數(shù)列
ini_df['buy_times']=ini_df['order_time'].groupby(ini_df['user_id']).rank()
#創(chuàng)建一個相同的輔助數(shù)據(jù)
assit_df=ini_df
assit_df['buy_times2']=assit_df['buy_times']+1
#合并數(shù)據(jù)
rebuy_df=pd.merge(ini_df,assit_df,left_on=['user_id','buy_times'],right_on=['user_id','buy_times2'],
how='left',suffixes=('','_pre'))
#篩選需要的列
rebuy_df=rebuy_df[['user_id', 'buy_times', 'order_id', 'order_time', 'product_type','amount',
'order_id_pre', 'order_time_pre', 'product_type_pre', 'amount_pre']]
#存儲數(shù)據(jù)
rebuy_df.to_csv('結(jié)果2.csv')

以上兩種處理方法,在80萬條數(shù)據(jù)的處理中,第一種方法跑了一天沒跑出來,而第二種幾分鐘之內(nèi)就出了結(jié)果。所以,處理問題時,思路相當(dāng)重要。
3、思路和解決方法3:
實際上,有了思路2就會發(fā)現(xiàn),解決問題的工具也顯得并不那么重要。既然數(shù)據(jù)已經(jīng)排好了序,觀察可以見pre列數(shù)據(jù)總滯后于原始數(shù)據(jù)一行。因此,在Excel中,我們首先使用公式計算出購買次數(shù)(buy_times);然后復(fù)制數(shù)據(jù)的第一行到倒數(shù)第二行,粘貼到pre列的第二行;最后篩選出buy_times=1,清除pre列的數(shù)據(jù)即得到最終結(jié)果。
數(shù)據(jù)資料附件:數(shù)據(jù) 密碼: dbup