python 數據錯位相減,上下兩行相減

今天接到一個需求,要求用對數據進行錯位相減。感覺寫得有點麻煩,如果其他方法,歡迎留言交流

數據說明:有客戶、消費日期、消費額度

求解目標:對於同一個客戶,對日期升序排序,如果下一個日期的消費額度大於上一個日期的消費額度,則標記,最終取出第一次發生時對應的較大的日期

最簡單的方法是使用 pandas.Series.shift 具體可參考官方文檔

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.shift.html

 

方法一是使用pandas.Series.shift,該方法可以方便地對數據進行移動

import pandas as pd
import numpy as np

df = pd.DataFrame({'persion':['A','A','A','A','B','B','B','B','B', 'C' ,'D','D','D']
                   , 'date':[0, 1, 6,  4, 1, 7, 4, 5, 6, 3, 1, 2, 3]
                   , 'price':[1, 5, 3, 0, 2, 4, 5, 8, 3, 5, 7, 7, 7 ]})

# 組內排序
df['sort_id'] = df['date'].groupby(df['persion']).rank()
df.sort_values(by = ['persion', 'sort_id'], axis=0, inplace=True) 
df['price_y'] = df["price"].shift(1)

 

方法二是自己寫的完整的數據處理方法,比較複雜,可作參考

import pandas as pd
import numpy as np

df = pd.DataFrame({'persion':['A','A','A','A','B','B','B','B','B', 'C' ,'D','D','D']
                   , 'date':[0, 1, 6,  4, 1, 7, 4, 5, 6, 3, 1, 2, 3]
                   , 'price':[1, 5, 3, 0, 2, 4, 5, 8, 3, 5, 7, 7, 7 ]})

# 組內排序
df['sort_id'] = df['date'].groupby(df['persion']).rank()
df.sort_values(by = ['persion', 'sort_id'], axis=0, inplace=True) 

# 添加每個persion的記錄數
persion_dt = df['persion']
persion_u = list(persion_dt.unique())
persion_cout =  df['persion'].value_counts().to_dict()
persion_dt_dict = persion_dt.to_dict()
for key, value in persion_dt_dict.items():
    persion_dt_dict[key] = persion_cout[value]

df['persion_cout'] = persion_dt_dict.values() # 添加每個id的統計值


# 數據移動,將下一條數據移動到上一行
fill_data = pd.DataFrame({'date':[0], 'price':[0]}) # 填充爲0, 也可以是其他值
# df.loc[df['persion']==col_value, ['date', 'price']][1:].append(fill_data) 使移動後的數據行數與移動前一致
slice_data = {col_value: df.loc[df['persion']==col_value, ['date', 'price']][1:].append(fill_data) for col_value in persion_u }

new_data = pd.DataFrame()
for key, value in slice_data.items():
    new_data = new_data.append(value)
     
new_data.reset_index(drop=True, inplace=True)


# 將移動後的數據與原數據拼接
all_data = pd.merge(df, new_data, how='inner', left_index=True, right_index=True)
all_data['diff'] = all_data['price_y'] - all_data['price_x']


# 如果persion只有一條記錄,保留;如果每個月的price一樣,則保留最早的記錄
all_data['flag'] = (all_data['persion_cout']==1) | (all_data['diff']>=0) 
all_data2 = all_data[all_data['flag'] == True]

data_select = all_data2.groupby('persion', as_index=False).first() # 保留第一次取得的最大值

# 將填充的0值改爲有效值
data_select.loc[data_select['date_y']==0, 'date_y'] = data_select.loc[data_select['date_y']==0, 'date_x'] 

# 刪除無用的列
data_select.drop(['sort_id', 'persion_cout', 'diff', 'flag'], axis=1, inplace=True)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章