数据探索式分析
导入必要的包
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import datetime
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
用户申购赎回数据表
df=pd.read_csv('user_balance_table.csv')
df.head()
#查看数据的数据类型和大小
df.info()
df.shape
#可视化数据的空值
cols = df.columns # 选取所有列
colours = ['#000099', '#ffff00'] # 黄色为缺失数据
sns.heatmap(df[cols].isnull(), cmap=sns.color_palette(colours))
可视化数据的空值,可以观察出数据空值的在整体中的位置。
#求出数据特征的相关性
sns.heatmap(df.corr('spearman'),linewidths=0.1)
由热力图可以看出,total_purchase(总购买量)与tBalance(今日余额),yBalance(昨日余额)有较大的正相关,购买当然看余额的额度,这个很显然成立。另外share_amt(今日收益)与tBalance(今日余额),yBalance(昨日余额),total_purchase(总购买量)有较大正相关性,余额越多,所得的收益越多,这个也比较明显,另外收益越多,购买量越大。
#将report_date列转为时间格式
df['date']=pd.to_datetime(df['report_date'],format='%Y%m%d')
df=df.drop(columns='report_date')
#对每一天的数据聚合
group_df=df.groupby(['date'])[['total_purchase_amt','total_redeem_amt']].sum().reset_index()
group_df['day']=group_df['date'].dt.day
group_df['month']=group_df['date'].dt.month
group_df['weekday']=group_df['date'].dt.weekday
group_df['year']=group_df['date'].dt.year
#查看数据大小
print(group_df.shape)
group_df.head()
#画出两者的时间序列图
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(18,6))
plt.plot(group_df['date'],group_df['total_purchase_amt'],label='purchase')
plt.plot(group_df['date'],group_df['total_redeem_amt'],label='redeem')
plt.xlabel('time')
plt.ylabel('amount')
plt.legend(loc='best')
总购买量2013年整体呈上升的趋势,到2014年1月末到峰值,这段时间正好是过年的时期,总购买量升高合理。而总赎回量总体波动式上升,直到2014年3月以后两者呈现出周期波动。该周期可为后面的模型做铺垫。
#异常值分析
fig=plt.figure(figsize=(12,5))
ax=plt.subplot(1,2,1)
sns.boxplot(x='weekday',y='total_purchase_amt',data=group_df)
ax=plt.subplot(1,2,2)
sns.boxplot(x='weekday',y='total_redeem_amt',data=group_df)
其中,总购买量在不同月份中有不少大于上须线,存在异常值,总赎回量没有发现异常值。周莫的总购买量和总赎回量普遍低于工作日。
获取具体异常值对应的时间:
import numpy as np
def boxerror(i):
redeem_25p=np.percentile(group_df['total_purchase_amt'][group_df['weekday'] == i],25)
redeem_75p=np.percentile(group_df['total_purchase_amt'][group_df['weekday'] == i],75)
UL=redeem_75p+1.5*(redeem_75p-redeem_25p)
vary=group_df[['date','total_purchase_amt','weekday']][(group_df['weekday'] == i) &
(group_df['total_purchase_amt'] > UL)]
return pd.to_datetime(vary['date'].values,format='%Y%m%d')
for i in range(7):
print(boxerror(i))
可以看出,这段时间也属于过年期间,在时间序列图的峰值附近,所以这几个的数据正常。
#观察总购买量和总赎回量的组成部分
fig=plt.figure(figsize=(15,7))
group_df2=df.groupby(['date'])[['date','total_purchase_amt','total_redeem_amt','direct_purchase_amt',
'purchase_bank_amt','purchase_bal_amt','direct_purchase_amt',
'share_amt','consume_amt','transfer_amt']].sum().reset_index()
col=group_df2.columns
plt.plot(group_df2['date'],group_df2[col[1]],label='sum_purchase')
plt.plot(group_df2['date'],group_df2[col[4]],label='purchase_bank')
plt.plot(group_df2['date'],group_df2[col[5]],label='purchase_bal')
plt.legend(loc='best')
可以看出用户的总购买量的大部分都是由银行卡直接支付,而不是余额支付。
#观察redeem的组成部分
fig=plt.figure(figsize=(15,7))
plt.plot(group_df2['date'],group_df2[col[2]],label='sum_redeem')
plt.plot(group_df2['date'],group_df2[col[8]],label='consume_amt')
plt.plot(group_df2['date'],group_df2[col[9]],label='transfer_amt')
plt.legend(loc='best')
可以看出,用户的总赎回量中转出占了绝大部分。
#周末和工作日的purchase和redeem对比
fig=plt.figure(figsize=(15,10))
weekend=group_df[['date','total_purchase_amt','total_redeem_amt']][group_df['weekday'] >= 5]
not_weekend=group_df[['date','total_purchase_amt','total_redeem_amt']][group_df['weekday'] < 5]
ax=plt.subplot(2,1,1)
plt.plot(weekend['date'],weekend['total_purchase_amt'],label='weekend_purchase')
plt.plot(not_weekend['date'],not_weekend['total_purchase_amt'],label='not_weekend_purchase')
plt.legend(loc='best')
ax=plt.subplot(2,1,2)
plt.plot(weekend['date'],weekend['total_redeem_amt'],label='weekend_redeem')
plt.plot(not_weekend['date'],not_weekend['total_redeem_amt'],label='not_weekend_redeem')
plt.legend(loc='best')
可以看出工作日的总购买量和总赎回量普遍高于周末。
#画总购买量和总赎回量的数据分布
fig=plt.figure(figsize=(15,10))
plt.subplot(1,2,1)
sns.distplot(group_df['total_purchase_amt'].dropna(),label='total_purchase')
plt.legend(loc='best')
plt.subplot(1,2,2)
sns.distplot(group_df['total_redeem_amt'].dropna(),label='total_redeem')
plt.legend(loc='best')
两个特征的数据都右偏,大部分时间序列内总购买量和总赎量是较低的。
#对weekday进行核密度估计分析
fig=plt.figure(figsize=(12,8))
ax=plt.subplot(2,1,1)
for i in range(7):
sns.kdeplot(group_df['total_purchase_amt'][group_df['weekday'] == i],label='purchase of '+str(i+1))
ax=plt.subplot(2,1,2)
for j in range(7):
sns.kdeplot(group_df['total_redeem_amt'][group_df['weekday'] == j],label='redeem of '+str(j+1))
从核密度估计也能看出来周末的总购买量和总赎回量是低于工作日的。
接下来对月份分析
#对月份聚合分析
fig=plt.figure(figsize=(15,9))
for i in range(1,13):
ax=plt.subplot(2,1,1)
sns.kdeplot(group_df['total_purchase_amt'][group_df['month'] == i],label='purchase of month '+str(i))
for i in range(1,13):
ax=plt.subplot(2,1,2)
sns.kdeplot(group_df['total_redeem_amt'][group_df['month'] == i],label='redeem of month '+str(i))
最终任务是预测14年九月份的总购买量和总赎回量,从以往数据看出,8月与9月的数据分布不贴合,按以往数据来,14年的9月总购买量和总赎回量都应该低于8月,9月的数据密度于1月的数据密度接近。
#分析月之间特征的相关性
group_df6=pd.get_dummies(group_df, columns = ['month'], drop_first=True)
coll=group_df6.columns
month1=[]
for i in group_df6[coll[-11:]].sum(1):
if i == 0:
month1.append(1)
else:
month1.append(0)
group_df6.insert(3,'month1',pd.Series(month1))
group_df6=group_df6.drop(columns=['day','weekday','year','weekdays'])
sns.heatmap(data=group_df6.corr('spearman'),linewidths=0.1)
总购买量于上半年成弱正相关性,与7月9月10月成弱负相关性。也再次说明了9月份的预测量按理应小于8月。
上海银行间同业拆放利率(Shibor)表
bank_data=pd.read_csv('mfd_bank_shibor.csv')
bank_data['date']=pd.to_datetime(bank_data['mfd_date'],format='%Y%m%d')
bank_data['weekday']=bank_data['date'].dt.weekday
bank_data['month']=bank_data['date'].dt.month
bank_data['year']=bank_data['date'].dt.year
bank_data.head()
#查看数据类型
bank_data.info()
#做出bank利率的时间序列图
fig=plt.figure(figsize=(15,5))
columns=bank_data.columns[1:9]
for i in columns:
plt.plot(bank_data['date'],bank_data[i],label=i)
plt.legend(loc='best')
时间序列图说明:主要是短期利率发生了较大波动,长期利率比较稳定。
#不同月份的核密度估计图
fig=plt.figure(figsize=(15,52))
for col,i in zip(columns,range(1,13)):
ax=plt.subplot(12,1,i)
for month in range(1,13):
sns.kdeplot(bank_data[col][bank_data['month'] == month],label= col+' month of ' + str(month))
plt.legend(loc='best')
通过核密度估计,在短期利率中数据分布有高有低,而长期利率极少时候有突然变大。下面来重点看看长期利率的数据分布。
#分析后4个利率的数据分布图
fig=plt.figure(figsize=(15,30))
for col,j in zip(columns[-4:],range(1,5)):
for month in range(1,13):
ax=plt.subplot(12,4,month+12*(j-1))
sns.distplot(bank_data[col][bank_data['month'] == month],label=col+'month of '+str(month))
plt.legend(loc='upper left',fontsize='small')
在3个月利率中1、2、3、4、5、12的利率比其他月份高,6个月利率中3、4月的利率较其他月高。9个月利率中3、4、5的利率较其他月高。1年利率中4、5、6的利率较其他月的利率高。所以说一般在这些月份中转出到银行的钱数应该会增加,也就是说总赎回量在这些月份可能比较高。
#查看他们对于的相关性
sns.heatmap(bank_data.drop(columns=['mfd_date','date']).corr('spearman'),linewidths=0.1)
由相关性热力图可知,短期利率与短期利率成正相关,长期利率与长期利率成正相关。并且随着month的增大,短期利率会稍稍增大,而长期利率会降低。
收益率表
benfit_data=pd.read_csv('mfd_day_share_interest.csv')
benfit_data.head()
#查看数据大小和类型
benfit_data.info()
benfit_data.shape
这个数据的样本量与文件1相同,可以合并分析
benfit_df=pd.concat([group_df,benfit_data],axis=1)
sns.heatmap(benfit_df.drop(columns=['date','mfd_date','weekdays']).corr('spearman'),linewidths=0.1)
可以发现总购买量,和总赎回量与万元利率(mfd_daily_yield)和七日年化利率(mfd_daily_yield)成正相关,总购买量包含收益,利率越大收益也越多,所以总购买量的强度比赎回量大。
fig=plt.figure(figsize=(15,9))
for i,j in zip(['total_purchase_amt','total_redeem_amt'],range(1,3)):
ax1=plt.subplot(2,1,j)
plt.plot(benfit_df['date'],benfit_df[i],label=i,c='y')
plt.legend(loc='upper left')
ax2=ax1.twinx()
plt.plot(benfit_df['date'],benfit_df['mfd_daily_yield'],label='mfd_daily_yield')
plt.plot(benfit_df['date'],benfit_df['mfd_7daily_yield'],label='mfd_7daily_yield')
plt.legend(loc='best')
时间序列图中,七日年化利率与总购买量、总赎回量的趋势较为接近,可以作为预测的一个特征。
#查看银行利率和余额表的收益对比(分长短期)
#短期
fig=plt.figure(figsize=(15,9))
ax=plt.subplot(2,1,1)
plt.plot(benfit_df['date'],benfit_df['mfd_daily_yield'],label='mfd_daily_yield')
plt.plot(benfit_df['date'],benfit_df['mfd_7daily_yield'],label='mfd_7daily_yield')
for col in columns[:4]:
plt.plot(bank_data['date'],bank_data[col],label=col)
plt.legend(loc='best')
ax=plt.subplot(2,1,2)
plt.plot(benfit_df['date'],benfit_df['mfd_daily_yield'],label='mfd_daily_yield')
plt.plot(benfit_df['date'],benfit_df['mfd_7daily_yield'],label='mfd_7daily_yield')
for col in columns[4:]:
plt.plot(bank_data['date'],bank_data[col],label=col)
plt.legend(loc='best')
总体上,余额表与银行长期利率更相似,不过也存在些许波动,但是上文分析出银行占购买量的大部分,所以余额宝可以采取增加短期利率来提高资金的输入和输出。