相关性分析
先对其中一支股票进行相关性分析,获取比较具有代表性的属性
不是非要进行,也是可以对所有属性进行聚类
# 3、相关性分析、聚类
path = r"G:\桌面\置顶\学习\课程实践3/"
df=pd.read_csv(path + "000513_main_report.csv",header = 1,encoding="utf-8")
# 转置
df1 = pd.DataFrame(df.values.T, index=df.columns, columns=df.index)
# 设置标题行
df1.columns = df1.iloc[0]
df1 = df1.drop(df1.index[0])
# 时间序列
df1.index=pd.to_datetime(df1.index)
df = df1["2020"].replace('%','',regex=True).astype(float)
result2 = np.corrcoef(df, rowvar=False)
import seaborn as sns
sns.pairplot(df)
plt.savefig(path+'000513_main_report各参数分布图.png',dpi=100,bbox_inches='tight')
plt.cla()
import matplotlib.pyplot as plt
figure, ax = plt.subplots(figsize=(12, 12))
sns.heatmap(df.corr(), square=True, annot=True, ax=ax)
plt.savefig(path+'000513_main_report各参数相关性图.png',dpi=100,bbox_inches='tight')
plt.cla()
# 相关性最低的三个属性
# 每股未分配利润(元)
# 销售净利率
# 应收账款周转天数(天)
根据上述结果,我提取了3个相关性最低的属性
读取数据
批量读取文件夹中的股票文件,并提取上述三个属性
import os
dir_path = path + r"股票财务数据"
dfff = pd.DataFrame(columns=['每股未分配利润(元)','销售净利率','应收账款周转天数(天)','股票代码'])
for filepaths,dirnames,filenames in os.walk(dir_path):
for allDir in filenames:
if allDir.lower().endswith(('.xls')):
df = pd.read_excel(os.path.join(dir_path,allDir),header=1)
# 转置
df1 = pd.DataFrame(df.values.T, index=df.columns, columns=df.index)
# 设置标题行
df1.columns = df1.iloc[0]
df1 = df1.drop(df1.index[0])
# 时间序列
df1.index=pd.to_datetime(df1.index)
df = df1["2020"][['每股未分配利润(元)','销售净利率','应收账款周转天数(天)']].replace('%','',regex=True).replace('--','nan',regex=True).astype(float)
ys = pd.DataFrame(df.resample('Y')[['每股未分配利润(元)','销售净利率','应收账款周转天数(天)']].mean())
ys['股票代码'] = allDir.split("_")[0]
dfff = pd.concat([dfff,ys])
print(dfff.isnull().any())
数据归一化
def MinMaxNormalization(test_data):
return test_data.apply(lambda x:(x-np.min(x))/(np.max(x)-np.min(x)))
dfff[['每股未分配利润(元)','销售净利率','应收账款周转天数(天)']] = MinMaxNormalization(dfff[['每股未分配利润(元)','销售净利率','应收账款周转天数(天)']])
K-means聚
from sklearn.cluster import KMeans
# 设置为三个聚类中心
Kmeans = KMeans(n_clusters=3)
# 训练模型
Kmeans.fit(dfff[['每股未分配利润(元)','销售净利率','应收账款周转天数(天)']])
Kmeans.cluster_centers_ # 聚类中心
Kmeans.labels_ # 聚类结果
out_file = pd.DataFrame(columns=['每股未分配利润(元)','销售净利率','应收账款周转天数(天)','股票代码','聚类结果'])
out_file[['每股未分配利润(元)','销售净利率','应收账款周转天数(天)','股票代码']] = dfff
out_file['聚类结果'] = Kmeans.labels_
out_file.to_excel(os.path.join(dir_path,'聚类结果.xlsx'),index=False,encoding="utf_8_sig")
绘图-查看聚类结果
label_pred = Kmeans.labels_ #获取聚类标签
centroids = Kmeans.cluster_centers_ #获取聚类中心
inertia = Kmeans.inertia_ # 获取聚类准则的总和
mark = ['or', '^b', '+g', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
#这里'or'代表中的'o'代表画圈,'r'代表颜色为红色,后面的依次类推
j = 0
for i in label_pred:
plt.plot([dfff[j:j+1]["每股未分配利润(元)"]], [dfff[j:j+1]['销售净利率']], mark[i], markersize = 5)
j +=1
plt.title('每股未分配利润(元)-销售净利率的聚类视图')
plt.xlabel('每股未分配利润(元)')
plt.ylabel('销售净利率')
plt.savefig(path+'每股未分配利润(元)-销售净利率的聚类视图.png',dpi=100,bbox_inches='tight')
plt.cla()
j = 0
# plt.show()
for i in label_pred:
plt.plot([dfff[j:j+1]["每股未分配利润(元)"]], [dfff[j:j+1]['应收账款周转天数(天)']], mark[i], markersize = 5)
j +=1
plt.title('每股未分配利润(元)-应收账款周转天数(天)的聚类视图')
plt.xlabel('每股未分配利润(元)')
plt.ylabel('应收账款周转天数(天)')
plt.savefig(path+'每股未分配利润(元)-应收账款周转天数(天)的聚类视图.png',dpi=100,bbox_inches='tight')
plt.cla()
j = 0
for i in label_pred:
plt.plot([dfff[j:j+1]["应收账款周转天数(天)"]], [dfff[j:j+1]['销售净利率']], mark[i], markersize = 5)
j +=1
plt.title('应收账款周转天数(天)-销售净利率的聚类视图')
plt.xlabel('应收账款周转天数(天)')
plt.ylabel('销售净利率')
plt.savefig(path+'应收账款周转天数(天)-销售净利率的聚类视图.png',dpi=100,bbox_inches='tight')
plt.cla()
plt.figure("3D Scatter", facecolor="lightgray")
ax3d = plt.gca(projection="3d") # 创建三维坐标
plt.title('3D Scatter', fontsize=20)
ax3d.set_xlabel('每股未分配利润(元)', fontsize=14)
ax3d.set_ylabel('应收账款周转天数(天)', fontsize=14)
ax3d.set_zlabel('销售净利率', fontsize=14)
plt.tick_params(labelsize=10)
ax3d.scatter(dfff["每股未分配利润(元)"], dfff["应收账款周转天数(天)"], dfff['销售净利率'], s=20, c = label_pred,cmap="jet", marker="o")
plt.show()
有归一化的结果认真观察其实可以发现,事实上是聚类成功的,只是因为三维图形在二维不能准确表达。
没有归一化的结果这个聚类结果也很不错,很明显三个类别排列成一条直线。所以第一张图看起来很混乱。