资金流入流出——基于简单规则的预测及数据分析与探索
·
在B站中学习了BruceQD的课程实战分析,对阿里云天池AI实训平台“蚂蚁金服资金流入流出预测挑战赛”进行讲解。我自己也照猫画虎地跟着学习中......
数据集大家可以去找一找,应该比较容易找到,这个比赛时间跨度大+经典
一部分:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
df = pd.read_csv(r"C:\Users\28049\Desktop\user_balance_table.csv")
#先利用简单规则分析,临近数据,中位数,平均数,临近数据的中位数......去求各方案的总得分
sta = df.groupby("report_date",as_index=False)[["total_purchase_amt","total_redeem_amt"]].sum()
#划分数据集,实际预测9月份,先尝试预测8月份(已知)
train_offline = sta[sta["report_date"]<20140801]
test_offline = sta[sta["report_date"]>=20140801]
# 1.要预测8月份,就用临近的7月份
train_offline_1 = train_offline[train_offline["report_date"]>=20140701]
train_offline_1["total_purchase_amt_true"] = test_offline["total_purchase_amt"]
train_offline_1["total_redeem_amt_true"] = test_offline["total_redeem_amt"]
def mape(x_true,x_pred):
return (x_true-x_pred)/x_true
# 求申购和赎回的总得分,每一天单独计分
def sore (p_t,p_p,r_t,r_p,h=1) :
p_mape = mape(p_t,p_p)
r_mape = mape(r_t,r_p)
return 0.45*10*np.exp(-p_mape/h)+0.55*10*np.exp(-r_mape/h)
# 求总得分
# for i,row in train_offline_1.iterrows:
# sum+=sore(row["total_purchase_amt_true"],row["total_purchase_amt"],row["total_redeem_amt_true"],row["total_redeem_amt"],h=1)
# 2.平均数,20140801之前的所有数据
train_offline_2 = train_offline
train_offline_2["total_purchase_amt_mean"] = train_offline["total_purchase_amt"].mean()
train_offline_2["total_redeem_amt_mean"] = train_offline["total_redeem_amt"].mean()
# 3.中位数 median()
#......
# 4.基于周期因子的预测
# 周期因子=每日的均值(每一周的每一天)/总体均值
# 再乘base base=最后一周的平均客流
# 思路:先求各report_date对应的weekday(每天对应的星期),再求星期一...星期天的对应(purchase/redeem)均值(每一周的星期1的总和/周数)就得到了周期因子
sta_1 = sta
sta_1["report_date_new"] = pd.to_datetime(sta_1["report_date"].astype(str))
sta_1["weekday"] = sta_1["report_date_new"].dt.weekday+1
train_offline_3 = sta_1[sta_1["report_date"]<20140801]
test_offline_3 = sta_1[sta_1["report_date"]>=20140801]
zjz = train_offline_3["total_purchase_amt"].mean()
list_1 = list(train_offline_3["total_purchase_amt"])
list_3 = pd.DataFrame([list_1[i:i+7] for i in range(0,len(list_1),7)])
list_3.columns = ["week_"+str(i+1) for i in range(7)]
list_4 = (list_3.mean())/zjz
base = list_3.loc[55].sum()/7
list_4 *= base
cont = [i+1 for i in range(7)]
dict_1 = dict(zip(cont,list_4))
test_offline_3["total_purchase_amt_new"] = test_offline_3["weekday"].apply(lambda x:dict_1[x])
# redeem 也一样
# 数据分析与探索(可视化)
# 时序图,时间序列
plt.figure(figsize=(12,6))
plt.plot(sta_1["report_date_new"],sta_1["total_purchase_amt"],label='purchase')
plt.plot(sta_1["report_date_new"],sta_1["total_redeem_amt"],label='redeem')
plt.legend(loc='best')
plt.show()
# 在2014-4月份后,数据才达到稳定,所以,可用的数据是2014-4之后的数据
# 箱型图
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
sns.boxplot(x='weekday',y='total_purchase_amt',data=sta_1)
plt.subplot(1,2,2)
sns.boxplot(x='weekday',y='total_redeem_amt',data=sta_1)
plt.show()
# 折线图
sns.relplot(x="weekday",y="total_purchase_amt",data=sta_1,kind='line',aspect=2,height=6)
plt.show()
以上是基于简单规则+周期因子的预测,通过可视化分析,我们发现在2014-4月之后的数据是稳定的,是可利用的。
再通过看weekday与申购/赎回总额之间的相关性,其在周一到周四较稳定,5,6,7有所下降,依次周期循环。
二部分:
# 利用spearman相关系数,去看weekday与申购/赎回的关系,绘制热力图
# 正相关 一个变量增加时,另一个变量倾向于增加
# 负相关 一个变量增加时,另一个变量倾向于减少
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
import seaborn as sns
from matplotlib import pyplot as plt
from 资金流入流出_1 import train_offline_3
df = pd.read_csv(r"C:\Users\28049\Desktop\user_balance_table.csv")
enconder = OneHotEncoder()
weekday_feats = enconder.fit_transform(np.array(train_offline_3["weekday"]).reshape(-1,1)).toarray()
train_offline_4 = pd.concat([pd.DataFrame(weekday_feats),train_offline_3],axis=1)
a = train_offline_4[list(range(7))+["total_purchase_amt","total_redeem_amt"]].corr("spearman")
#将weekday进行编码,例如:星期一:1000000
# 星期二:0100000
# 因为星期之间不存在大小关系,非连续性
# 热力图
sns.heatmap(a,vmax=0.2,vmin=-0.2) # 调节色柱
plt.show()
三部分:
对于建模分析的角度:
#只能利用2024-4月之后的数据,进行建模
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
from sklearn.ensemble import RandomForestRegressor
df = pd.read_csv(r"C:\Users\28049\Desktop\user_balance_table.csv")
sta = df.groupby("report_date",as_index=False)[["total_purchase_amt","total_redeem_amt"]].sum()
sta["report_date_new"] = pd.to_datetime(sta["report_date"].astype(str))
sta["weekday"] = sta["report_date_new"].dt.weekday+1
train_offline = sta[(sta["report_date"]>=20140401) & (sta["report_date"]<20140801)].reset_index(drop=True)
test_offline = sta[sta["report_date"]>=20140801].reset_index(drop=True)
encoder = OneHotEncoder()
df_1 = pd.concat([train_offline,test_offline]).reset_index(drop=True)
weekday_all = encoder.fit_transform(np.array(df_1["weekday"]).reshape(-1,1)).toarray()
tmp = pd.DataFrame(weekday_all[:len(train_offline)])
for i in range(7):
train_offline["is_weekday"+str(i+1)] = tmp[i]
tmp = pd.DataFrame(weekday_all[len(train_offline):])
for i in range(7):
test_offline["is_weekday"+str(i+1)] = tmp[i]
#建模(以purchase为例)
clf = RandomForestRegressor(n_estimators=500,max_depth=6)
clf.fit(train_offline[["is_weekday"+str(i+1) for i in range(7)]],train_offline["total_purchase_amt"])
test_offline["predict"] = clf.predict(test_offline[["is_weekday"+str(i+1) for i in range(7)]])
print(test_offline[["predict","total_purchase_amt"]])
#线上测试,线下可将test加入到train中
之前的基于简单规则得到的中位数,平均数,周期因子等特征,也可以当作特征,去建模。
虽然“主播”还什么都不会,但只有我们努力学习,大家都能得偿所愿!
更多推荐
所有评论(0)