阿里云天池-- 汽车产品聚类分析

一 汽车产品聚类分析说明

1.1赛题背景

赛题以竞品分析为背景,通过数据的聚类,为汽车提供聚类分类。对于指定的车型,可以通过聚类分析找到其竞品车型。通过这道赛题,鼓励学习者利用车型数据,进行车型画像的分析,为产品的定位,竞品分析提供数据决策。

1.2赛题数据

image.png

1.3赛题任务

对该汽车数据进行聚类分析,并找到vokswagen汽车的相应竞品。

二、作答

2.1数据处理

2.1.1数据导入

import pandas as pd
import numpy as np
import matplotlib.pyplt as plt
car_data=pd.read_csv('./car_price.csv')
car_data.head()
image.png

2.1.2查看数据类型以及重复项

car_data.info()#查看26个字段的类型
car_data.duplicated().sum()#查看是否有重复项
image.png
##调取每个类型下(int 64)的数据,并进行描述统计
car_data_int=car_data.select_dtypes(include='int64')
car_data_int.describe()#根据结果显示int类型的数据正常,没有异常值
image.png
##调取每个数值类型(float)下的数据,并进行描述统计
car_data_float=car_data.select_dtypes(include='float64')
car_data_float.describe()#根据结果显示float64类型的数据正常,没有异常值
image.png
##调取文本类型下的数据,并进行描述统计,查看文本值的分布情况
car_data_object=car_data.select_dtypes(include='object')
for i in  car_data_object.columns:
     print(i)
     print(set(car_data_object[i]))#set是一组dict字典形式,可以过滤重复值
image.png

将潜在的数值型文本数据进行转化

object_dic={'two':2,'four':4, 'six':6, 'eight':8, 'twelve':12, 'three':3, 'five':5, 'four':4}
car_data['doornumber']=car_data['doornumber'].replace(object_dic)
car_data['cylindernumber']=car_data['cylindernumber'].replace(object_dic)

除此以外可以看出品牌名中有些错误拼写的问题,竞品分析是以'volkswagen'为基础,因此需要先对品牌名称进行处理。处理方法:1.只留下品牌名 2.改正拼写错误

car_data['CarName']=car_data['CarName'].apply(lambda x :str(x).split(' ')[0])
car_data.head()
#注意用str(x) 而不是x.split() 否则报错
image.png

其中车辆品牌列已经完全获取品牌名,但是还存在拼写错误,用replace进行替换

#查看有哪些品牌名
car_data_name=set(car_data['CarName'])
car_data_name
image.png

'maxda'、'porsche'等属于拼写错误

#改正拼写及大小写错误
car_data_name={'maxda':'mazda','Nissan':'nissan','porsche':'porcshce','toyouta':'toyota','vokswagen':'volkswagen','vw':'volkswagen'}#字典形式
car_data['CarName']=car_data['CarName'].replace(car_data_name)
car_data_name2=set(car_data['CarName'])
car_data_name2
image.png

更改以后只剩22个品牌

2.2 数据分析

2.2.1 数值型异常值分析--箱型图与描述型统计相结合

car_data_float=car_data.select_dtypes(include='float64')
car_data_float.describe()
image.png

绘制数值型的箱型图

num_cols=car_data_float.columns
import seaborn as sns
fig=plt.figure(figsize=(12,8))
i=1

  for col in num_cols:
    ax=fig.add_subplot(2,4,i)
    sns.boxplot(data=car_data[col],ax=ax,sym="r+")
    i=i+1
    plt.title(col)
plt.show() 
image.png

对显示出异常值的wheelbase、carwidth等变量进行复查,从描述性统计中确定该变量是否真正有异常值。经过确定这部分变量的异常符合现实情况。

2.2.2 数值型数据相关性分析

#对数值型进行相关性分析,corr只对数值型进行操作
car_data_corr=car_data.corr()
car_data_corr
image.png
#使用mask只绘制热力图其中的一半
mask = np.zeros_like(car_data_corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
        f, ax = plt.subplots(figsize=(25, 10))
        ax = sns.heatmap(car_data_corr,annot = True, mask=mask,vmin=0,vmax=1, square=True)
ax.set_title('correlation between car')
image.png

相关系数分类: 0.8-1.0 极强相关;0.6-0.8 强相关;0.4-0.6 中等程度相关;0.2-0.4 弱相关;0.0-0.2 极弱相关或⽆相关
可以看出:车长与车宽、轴距具有极强相关关系,与空车重有强相关关系;发动机大小与车宽强相关,与空车重和气缸数量极强相关;马力和发动机大小、气缸数量、空车重也具有相关关系,城市里程和公路里程强相关,价格和空车重、发动机大小有关。可见数据冗余,应该进行处理

2.2.3 划分车辆类型--以车长为依据

在汽车销售等实际业务中,很多消费者购买需求有时会根据考虑车型的⼤⼩来考虑。
欧系分类,按德国标准,车型⼤⼩可按照车长,轴距划分为6类:
1、微型车(A00):车长⼩于3.7M;轴距⼩于:2.35M;
2、⼩型车(A0):车长⼩于4.3M;轴距⼩于:2.5M;
3、紧凑型车(A):车长⼩于4.6M;轴距⼩于:2.7M;
4、中型车(B):车长⼩于4.9M;轴距⼩于:2.8M;
5、中⼤型车(C):车长⼩于5.1M;轴距⼩于:2.9M;
6、豪华车(D):车长⼤于5.1M;轴距⼤于:2.9M。
⽽要注意,数据集中车长宽⾼和轴距单位均为英⼨,需要进⾏单位的转换:1英⼨=0.0254⽶。
按车⾝长度分类界限:微型车: A00 <145.67 ;⼩型车: A0<169.29 ;紧凑型车:A <181.10 ;中型车: B <192.91 ;中⼤型车:C<200.79;大型车:D>200.79

根据分类标准进行分箱操作
bin=[min(car_data.carlength)-0.01,145.67,169.29,181.10,192.91,200.79,max(car_data.carlength)+0.01]#确定分组标准
groupnames=['A00','A0','A','B','C','D']#定义箱名
car_group=pd.cut(car_data.carlength,bin,labels=groupnames)
#新建一列将分组情况放入数据集
car_data['cargroup']=car_group
car_data.head()
image.png

三 聚类前预处理

3.1 特征数值化

3.1.1 LabelEncoder编码

LabelEncoder编码是将有大小意义的非数值变量进行编码,比如cargroup('A00'<'A0'<'A'<'B'<'C'<'D')

cardata=car_data.copy()
cardata.head()
cardata['cargroup']=cardata['cargroup'].astype(str)
#进行编码之前将cargroup转换成字符型,否则报错
from sklearn.preprocessing import LabelEncoder
cargroup_copy=LabelEncoder().fit_transform(cardata['cargroup'])
cardata['cargroup']=cargroup_copy

3.1.2 one-hot编码

对没有大小意义的非数值变量进行one-hot编码

#剔除车长度,用车型代替(车型是根据车长来的)
cardata=cardata.drop(['carlenrth'],axis=1)
cardata_features=cardata.select_dtypes(include='object')
cardata_features.head()
image.png
#进行one-hot编码
cardata_onehot=pd.get_dummies(cardata_features,drop_first='True')#drop_first去除冗余特征,避免特征重复
cardata2=cardata.join(cardata_onehot).drop(cardata_features,axis=1)#把处理后的数据加上,处理前的数据删除
cardata2.info()
onehot后的结果.png

3.2 数据标准化处理

由于数值存在量纲的不同,因此对其进行区间化(标准化的一种),把值限定在0~1之间

from sklearn.preprocessing import MinMaxScaler
cardata2=MinMaxScaler().fit_transform(cardata2)
cardata2.shape
标准化的结果是多维数组.png
#将数据转化成矩阵形式
cardata2=pd.DataFrame(cardata2)
cardata2.head()

3.3 利用PCA对高维数据降维

主成分,将线性相关的高维数据转换成线性无关的低维数据,注意不是原特征变量,而是新建立的变量

from sklearn.decomposition import PCA
pca=PCA(.99)#可解释方差比例设为0.99
cardata3=pca.fit_transform(cardata2)
ratio=pca.explained_variance_ratio_
print('各主成分的解释方差占比:', ratio)
print('降维后有几个成分:', pca.n_components_)
cum_ratio=np.cumsum(ratio)
print('累计解释方差占比:',cum_ratio)
降维结果.png

由原来的61个成分降维至39个成分

fig=plt.figure(figsize=(10,5))
X=range(1,len(ratio)+1)
plt.bar(X,ratio,edgecolor='blue')
plt.plot(X,cum_ratio,'r.-')
plt.xlabel('PCA')
plt.ylabel('explained_variance_ratio_')
plt.grid(b="True",axis="y")
plt.grid(b="True",axis="x")
plt.show()
PCA结果.png

根据28法则,累计解释方差达到80%的主成分有12个,保留主成分

pca=PCA(n_components=12)#提取出12个主成分
cardata4=pca.fit_transform(cardata3)
print('降维后累计解释方差占比:',sum(pca.explained_variance_ratio_))
cardata4=pd.DataFrame(cardata4)#将多维数组转化成矩阵形式
image.png

四 利用K-Means进行数据聚类

4.1 肘部法确定聚类个数

k均值聚类有一个缺点,无法提前确定聚类的个数,因此使用肘部法,先确定聚类个数

from sklearn.cluster import KMeans
sse=[]
kvals=range(1,20)#20是自己设置,确保明显的看到拐点
for k in kvals:
    Kmeans=KMeans(n_clusters=k,init='k-means++',n_init=10,max_iter=300,random_state=0)#构造聚类器
    Kmeans.fit(cardata4)#放入数据
    sse.append(Kmeans.inertia_)
X=kvals
plt.xlabel('k')
plt.ylabel('sse')
plt.plot(X,sse,'o-')
plt.grid(b="True",axis="y")
plt.grid(b="True",axis="x")
plt.show()#可以看出拐点在第7个(不太明显)
肘部法确定聚类个数.png

进行k-means均值聚类,散点图查看聚类效果

kms=KMeans(n_clusters=5,init='k-means++',n_init=10,max_iter=300,random_state=123)#random_state没有特殊含义,保证每次运行代码选取的中心点一致
#n_clusters先根据肘部法设置为7,后尝试了7的左右值发现,聚类个数为5的情况下聚类效果最好
kms.fit(cardata4)
label=kms.labels_#获取聚类结果
print(label)
image.png
fig=plt.figure(figsize=(8,8))
plt.scatter(cardata4[label==0].iloc[:,0],cardata4[label==0].iloc[:,1],c="red",marker='o',label='class0')#红色圆圈样式绘制散点图
plt.scatter(cardata4[label==1].iloc[:,0],cardata4[label==1].iloc[:,1],c="red",marker='+',label='class1') #红色圆圈样式绘制散点图
plt.scatter(cardata4[label==2].iloc[:,0],cardata4[label==2].iloc[:,1],c="green",marker='o',label='class2') #红色圆圈样式绘制散点图
plt.scatter(cardata4[label==3].iloc[:,0],cardata4[label==3].iloc[:,1],c="green",marker='+',label='class3') #红色圆圈样式绘制散点图
plt.scatter(cardata4[label==4].iloc[:,0],cardata4[label==4].iloc[:,1],c="blue",marker='o',label='class4') #红色圆圈样式绘制散点图
plt.scatter(cardata4[label==5].iloc[:,0],cardata4[label==5].iloc[:,1],c="blue",marker='+',label='class5') #红色圆圈样式绘制散点图
plt.xlabel('pc1')
plt.ylabel('pc2')  
plt.title('K-Means PCA')
plt.show()
聚类散点图.png

通过对比聚类分析图,发现5类的聚类效果最好(省略了一步专业的评估,我不会哈哈哈)

五 聚类结果展示

将k=5时的分类结果数据(label)放到原特征数据中

cardata_km=car_data.copy()
cardata_km['km_result']=label
#统计每个集群,每个车品牌的车型数
cardata_km_num2=cardata_km.groupby(by=['km_result','CarName'])['car_ID'].count()
cardata_km_num2
不完全展示.png

其中0,1,4中有volkswage,把这三类的数据提取出来并合并

cardata_km_result0=cardata_km.loc[cardata_km['km_result']==0]
cardata_km_result1=cardata_km.loc[cardata_km['km_result']==1]
cardata_km_result4=cardata_km.loc[cardata_km['km_result']==4]
cardata_km_result=pd.concat([cardata_km_result0,cardata_km_result1,cardata_km_result4],axis=0)#pd.concat将数据合并,行向合并
cardata_km_result.loc[cardata_km_result['CarName']=='volkswagen']#查看'volkswagen'的车型
image.png
#A车型占比最大,故将A车型下的品牌作为volkswagen的竞品
dfa=df.loc[df['cargroup']=='A']
df_com=set(dfa['CarName'])
df_com
竞品结果.png

综上,'audi', 'dodge','honda', 'isuzu', 'mazda', 'mitsubishi', 'nissan', 'plymouth', 'renault', 'subaru','toyota'为 'volkswagen'的竞品品牌。
注:更完善的是细化至品牌内部,根据车型的车身重、动力性、安全性等对volkswagen及竞品的优劣势进行分析,给出销售建议。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容