在链家爬了一些二手房数据,尝试用聚类进行分析。
1. 一些简单的准备工作:导包、导数据、简单的数据提取
# 导入常用的包
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
import pickle
import time
import multiprocessing
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 导入数据
df_shanghai = pd.read_csv('sh_ershou_clean.csv', index_col = 0)
df_hangzhou = pd.read_csv('hz_ershou_clean.csv', index_col = 0)
print('df_shanghai.shape:{}'.format(df_shanghai.shape))
print('df_hangzhou.shape:{}'.format(df_hangzhou.shape))
# 提取建房时间
df_shanghai['year'] = df_shanghai['info'].str.extract('([\d]+)年').astype('float')
df_shanghai['age'] = 2022-df_shanghai.year
2. 数据预处理
2.1 数值型:标准化
# 对数值型数据进行标准化
t= preprocessing.StandardScaler().fit(df_shanghai[df_shanghai.describe().columns])
df_shanghai_processed = pd.DataFrame(t.transform(df_shanghai[df_shanghai.describe().columns]))
df_shanghai_processed.columns = df_shanghai.describe().columns
2.2 字符型:labelencoding
# 类别型变量进行labelenconding
df_shanghai_processed['location1'] = df_shanghai.location1
le = preprocessing.LabelEncoder()
df_shanghai_processed['location1'] = le.fit_transform(df_shanghai_processed['location1'])
# 将label_encoding的映射关系记录下来
def pkl_save(filename, file):
#将file保存到filename中
output = open(filename, 'wb')
pickle.dump(file, output)
output.close()
pkl_save('shanghai_location1_labelencoding.pkl', le)
2.3 缺失值填充
# 缺失值填充
df_shanghai_processed.year.fillna(df_shanghai_processed.year.mean(), inplace = True)
df_shanghai_processed.age.fillna(df_shanghai_processed.age.mean(), inplace = True)
3. 调用kmodes包进行聚类
3.1 模型训练
from kmodes.kprototypes import KPrototypes
cate_index = [5] # 为类别型变量在columns中的索引
def TrainCluster(df, model_name=None, start_k=2, end_k=10):
print('training cluster')
K = []
SSE = []
silhouette_all=[]
models = [] #保存每次的模型
for i in range(start_k, end_k):
start = time.perf_counter ()
kproto_model = KPrototypes(n_clusters=i, n_jobs=multiprocessing.cpu_count())
kproto_model.fit(df_shanghai_processed,categorical=cate_index)
SSE.append(kproto_model.cost_) # 保存每一个k值的SSE值
K.append(i)
print('{}-prototypes SSE loss = {}'.format(i, kproto_model.cost_))
models.append(kproto_model) #保存每个k值对应的模型
end = time.perf_counter ()
print('Running time: %s Seconds'%(end-start))
return(K,SSE,models)
K, SSE, models = TrainCluster(df = df_shanghai_processed)
3.2 类别数量选择
# 决定选择5
plt.plot(K, SSE)
plt.xlabel('聚类类别数k')
plt.ylabel('SSE')
plt.xticks(K)
plt.title('用肘部法则来确定最佳的k值')
plt.show()
结果如下图:
3.3 确定类别数量k后,进行可视化等后续的分析处理
#确定了最佳的k值后:5
best_model = models[K.index(5)]
# 对样本类别进行标记
df_shanghai['labels_'] = best_model.labels_
# 提取每一簇的中心
center = pd.DataFrame(best_model.cluster_centroids_ )
center.columns = df_shanghai_processed.columns
# 还原每一簇中心,得到标准化之前对应的原始值
for col in center.columns[:-1]:
col_new = col+'_raw'
mean = df_shanghai[col].mean()
std = df_shanghai[col].std()
center[col_new] = center[col]*std+mean
print(col_new)
# 绘制散点图
colors1 = '#00CED1' #点的颜色
colors2 = '#DC143C'
col1 = 'total_price'
col2 = 'area'
for label in df_shanghai.labels_.unique():
if label != 3:
x = df_shanghai.loc[df_shanghai.labels_ == label, col1]
y = df_shanghai.loc[df_shanghai.labels_ == label, col2]
plt.scatter(x, y, label = str(label), alpha = 0.2)
plt.legend()
簇中心各分量如下:
散点图如下:
remark:
只能说跑通了调用kprototypes进行聚类的流程,后续考虑调用高德或者百度地图的接口,添加房子到人民广场的距离这一变量,去掉location这个类别型变量直接利用kmeans进行聚类。
添加距离变量可参考:
Python:爬了下链家的小区数据,为数据分析弄素材~_Cyber的博客-CSDN博客_小区数据前言:最近在学数据分析,包括主成分分析、因子分析、聚类。。。等等,没有数据可不行啊,所以就把链家的小区数据给爬了一下,为后续的分析实战弄素材~一、数据爬取准备链家的网站还是很好爬的,地址很有标准,可以看到下图中有5391个小区,但是很多都是无效小区,而且单页只有30个小区且最多30页,所以我们需要从源码上了解具体结构。从第二页起,链接就变成pg2之类的,依次类推,就可以爬取30页以后的数...https://blog.csdn.net/weixin_42029733/article/details/93064205?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1.queryctr&spm=1001.2101.3001.4242.2&utm_relevant_index=4根据经纬度计算两地距离_weixin_34218890的博客-CSDN博客最近工作需要,网上搜索了下根据经纬度计算两地距离的方法,发现要么是几何法,画图、作一堆辅助线,然后证明推理,要么二话不说直接套公式。这篇文章介绍一种容易理解的方式来求这个距离。0b00 思路地球是个不规则的椭球体、为了简便我们当作球体来计算。 球体上两地的最短距离就是经过两点的大圆的劣弧长度。思路如下:弧长 ← 弦长(两点距离)...https://blog.csdn.net/weixin_34218890/article/details/88740639