欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python数据分析--Iris数据集实战

程序员文章站 2022-06-24 08:52:38
本次主要围绕Iris数据集进行一个简单的数据分析, 另外在数据的可视化部分进行了重点介绍. 环境 win8, python3.7, jupyter notebook 正文 1. 项目背景 鸢尾属(拉丁学名:Iris L.), 单子叶植物纲, 鸢尾科多年生草本植物, 开的花大而美丽, 观赏价值很高. ......

本次主要围绕iris数据集进行一个简单的数据分析, 另外在数据的可视化部分进行了重点介绍.

环境

win8, python3.7, jupyter notebook

正文

1. 项目背景

鸢尾属(拉丁学名:iris l.), 单子叶植物纲, 鸢尾科多年生草本植物, 开的花大而美丽, 观赏价值很高. 鸢尾属约300种, iris数据集中包含了其中的三种: 山鸢尾(setosa),  杂色鸢尾(versicolour), 维吉尼亚鸢尾(virginica), 每种50个数据, 共含150个数据. 在每个数据包含四个属性: 花萼长度,花萼宽度,花瓣长度,花瓣宽度, 可通过这四个属性预测鸢尾花卉属于 (山鸢尾, 杂色鸢尾, 维吉尼亚鸢尾) 哪一类.

2. 数据概览

数据来源: https://www.kaggle.com/benhamner/python-data-visualizations/data

2.1 读取数据

数据为csv文件, 读取数据:

import pandas as pd
df_iris = pd.read_csv('iris.csv')

2.2 查看前/后5行数据

#前5行
df_iris.head()
#后5行
df_iris.tail()

Python数据分析--Iris数据集实战

 Python数据分析--Iris数据集实战

通过这10行数据也就大致确定数据维度150行x6列以及各特征内的基本信息:

id: 鸢尾花编号

sepalengthcm: 花萼长度, 单位cm

sepalwidthcm: 花萼宽度, 单位cm

petallengthcm: 花瓣长度, 单位cm

petalwidthcm; 花瓣宽度, 单位cm

species: 鸢尾花种类.

2.3 查看数据整体信息

#查看数据整体信息
df_iris.info()
<class 'pandas.core.frame.dataframe'>
rangeindex: 150 entries, 0 to 149
data columns (total 6 columns):
id               150 non-null int64
sepallengthcm    150 non-null float64
sepalwidthcm     150 non-null float64
petallengthcm    150 non-null float64
petalwidthcm     150 non-null float64
species          150 non-null object
dtypes: float64(4), int64(1), object(1)
memory usage: 7.1+ kb

得出信息: 150行, 6列,4个64位浮点数, 1个64位整型, 1个python对象, 数据中无缺失值.

2.4 描述性统计

df_iris.describe()

花萼长度最小值4.30, 最大值7.90, 均值5.84, 中位数5.80, 右偏

花萼宽度最小值2.00, 最大值4.40, 均值3.05, 中位数3.00, 右偏

花瓣长度最小值1.00, 最大值6.90, 均值3.76, 中位数4.35, 左偏

花瓣宽度最小值0.10, 最大值2.50, 均值1.20, 中位数1.30, 左偏

按中位数来度量: 花萼长度 > 花瓣长度 > 花萼宽度 > 花瓣宽度

Python数据分析--Iris数据集实战

#注意这里是大写的字母o, 不是数字0.
df_iris.describe(include =['o']).t

总数150, 3个种类, 最大频数为50, 也就是每种都为50个. 注意top里的指的不是iris-versicolor最多, 是在频数相同的基础上按照字符串长度进行排名.

Python数据分析--Iris数据集实战

可以通过这样对每种进行计数:

df_iris.species.value_counts()
iris-versicolor    50
iris-virginica     50
iris-setosa        50
name: species, dtype: int64

通过以上, 大致了解数据的基本信息, 现想把species特征中的'iris-'字符去掉, 进入特征工程环节.

3. 特征工程

3.1 数据清洗

去掉species特征中的'iris-'字符.

#第一种方法: 替换
# df_iris['species']= df_iris.species.str.replace('iris-','')
#第二种方法: 分割
df_iris['species']= df_iris.species.apply(lambda x: x.split('-')[1])
df_iris.species.unique()
array(['setosa', 'versicolor', 'virginica'], dtype=object)

3.2 数据可视化

seaborn是一个python的可视化库, 它基于matplotlib, 这使得它能与pandas紧密结合, 并且提供了高级绘图界面, 能更方便地完成探索性分析.

我想在这个项目上对seaborn多加练习, 因此, 会对这部分内容着重介绍.

3.2.1 relplot

import seaborn as sns
import matplotlib.pyplot as plt
#sns初始化
sns.set()
#设置散点图x轴与y轴以及data参数
sns.relplot(x='sepallengthcm', y='sepalwidthcm', data = df_iris)
plt.title('sepallengthcm and sepalwidthcm data analysize')

Python数据分析--Iris数据集实战

花萼的长度和宽度在散点图上分了两个簇, 而且两者各自都有一定的关系. 鸢尾花又分为三个品种, 不妨看看关于这三个品种的分布.

#hue表示按照species对数据进行分类, 而style表示每个类别的标签系列格式不一致.
sns.relplot(x='sepallengthcm', y='sepalwidthcm', hue='species', style='species', data=df_iris )
plt.title('sepallengthcm and sepalwidthcm data by species')

Python数据分析--Iris数据集实战 

 可以看到setosa这种花的花萼长度和宽度有明显的线性关系, 当然其他两种也存在一定的关系, 花萼的属性看完了, 看下花瓣的:

#花瓣长度与宽度分布散点图
sns.relplot(x='petallengthcm', y='petalwidthcm', hue='species', style='species', data=df_iris )
plt.title('petallengthcm and petalwidthcm data by species')

花的品种和花瓣的长度, 宽度之间存在一定的关系.

Python数据分析--Iris数据集实战

 另外, 还可以对比花萼与花瓣的长度, 花萼与花瓣的宽度之间的关系.

#花萼与花瓣长度分布散点图
# sns.relplot(x='sepallengthcm', y='petallengthcm', hue='species', style='species', data=df_iris )
#plt.title('sepallengthcm and petallengthcm data by species')
#花萼与花瓣宽度分布散点图
sns.relplot(x='sepalwidthcm', y='petalwidthcm', hue='species', style='species', data=df_iris )
plt.title('sepalwidthcm and petalwidthcm data by species')

Python数据分析--Iris数据集实战Python数据分析--Iris数据集实战

花萼的长度与花瓣的宽度, 花萼的宽度与花瓣的长度之间应当也存在某种关系:

#花萼的长度与花瓣的宽度分布散点图
# sns.relplot(x='sepallengthcm', y='petalwidthcm', hue='species', style='species', data=df_iris )
#plt.title('sepallengthcm and petalwidthcm data by species')
#花萼的宽度与花瓣的长度分布散点图
sns.relplot(x='sepalwidthcm', y='petallengthcm', hue='species', style='species', data=df_iris )
plt.title('sepalwidthcm and petallengthcm data by species') 

Python数据分析--Iris数据集实战Python数据分析--Iris数据集实战

id编号与花萼长度, 花萼宽度, 花瓣长度, 花瓣宽度之间有没有关系呢:

#花萼长度与id之间关系图
sns.relplot(x="id", y="sepallengthcm",hue="species", style="species",kind="line", data=df_iris)
plt.title('sepallengthcm and id data analysize')
#花萼宽度与id之间关系图
sns.relplot(x="id", y="sepalwidthcm",hue="species", style="species",kind="line", data=df_iris)
plt.title('sepalwidthcm and id data analysize')
#花瓣长度与id之间关系图
sns.relplot(x="id", y="petallengthcm",hue="species", style="species",kind="line", data=df_iris)
plt.title('petallengthcm and id data analysize')
#花瓣宽度与id之间关系图
sns.relplot(x="id", y="petalwidthcm",hue="species", style="species",kind="line", data=df_iris)
plt.title('petalwidthcm and id data analysize')

可以得到信息: id中前50个为setosa, 51到100为versicolour, 101到150为virginica, 以及每个种类对应属性值的范围, 每个种类中的属性与其对应的id没有明确的关系.

Python数据分析--Iris数据集实战

3.2.2 jointplot

sns.jointplot(x='sepallengthcm', y='sepalwidthcm', data=df_iris)
sns.jointplot(x='petallengthcm', y='petalwidthcm', data=df_iris)

散点图和直方图同时显示, 可以直观地看出哪组频数最大, 哪组频数最小.

Python数据分析--Iris数据集实战Python数据分析--Iris数据集实战

对于频数的值, 在散点图上数点的话, 显然效率太低, 还易出错, 下面引出distplot

3.2.3 distplot

#绘制直方图, 其中kde=false表示不显示核函数估计图,这里为了更方便去查看频数而设置它为false.
# sns.distplot(df_iris.sepallengthcm,bins=8, hist=true, kde=false)
# sns.distplot(df_iris.sepalwidthcm,bins=13, hist=true, kde=false)
# sns.distplot(df_iris.petallengthcm, bins=5, hist=true, kde=false)
sns.distplot(df_iris.petalwidthcm, bins=5, hist=true, kde=false)

我这里的分组是按照上面jointplot里的组数进行设置, 现在就很直观地看到各组对应的频数

Python数据分析--Iris数据集实战

前面我们已经通过describe()方法计算出四个属性所对应的四分位数, 最大值以及最小值等统计量. 这些均是以表格的形式展示, 我们下面就介绍怎么以图样的形式展示四分位数.

3.2.4 boxplot

boxplot所绘制的就是箱线图, 它能显示出一组数据的最大值, 最小值, 四分位数以及异常点.

对于异常点的定义: 区间[q1-1.5iqr, q3+1.5iqr]之外的点, 其中q1下四分位数(25%), q3上四分位数(75%), iqr=q3-q1

在seaborn.boxplot中, 箱线图的画法分两种情况

如果数据中无异常点, 那么箱线图的下边缘就是数据中的最小值, 上边缘就是数据中的最大值, 即下图的实线部分(虚线以及红点部分不会显示)

Python数据分析--Iris数据集实战

如果数据中有异常点, 那么箱线图的下边缘limit1指的是区间[q1-1.5iqr, q3+1.5iqr]内的最小值, 上边缘limit2指的是区间内的最大值, 即下图的实线部分(虚线以及红点部分不会显示)

Python数据分析--Iris数据集实战

#比如数据中的sepallengthcm属性
sns.boxplot(x='sepallengthcm', data=df_iris)
#比如数据中的sepalwidthcm属性
sns.boxplot(x='sepalwidthcm', data=df_iris)

Python数据分析--Iris数据集实战Python数据分析--Iris数据集实战

 为了更直观地对比四个属性之间的关系, 我将四个属性对应的数值合并在新的dataframe iris中.

#对于每个属性的data创建一个新的dataframe
iris1 = pd.dataframe({"id": np.arange(1,151), 'attribute': 'sepallengthcm', 'data':df_iris.sepallengthcm, 'species':df_iris.species})
iris2 = pd.dataframe({"id": np.arange(151,301), 'attribute': 'sepalwidthcm', 'data':df_iris.sepalwidthcm, 'species':df_iris.species})
iris3 = pd.dataframe({"id": np.arange(301,451), 'attribute': 'petallengthcm', 'data':df_iris.petallengthcm, 'species':df_iris.species})
iris4 = pd.dataframe({"id": np.arange(451,601), 'attribute': 'petalwidthcm', 'data':df_iris.petalwidthcm, 'species':df_iris.species})
#将四个dataframe合并为一个.
iris = pd.concat([iris1, iris2, iris3, iris4])
#绘制箱线图
sns.boxplot(x='attribute', y='data', data=iris)

对下图做一下简单分析: 就中位数来说, sepallenthcm > petallengthcm > sepalwidthcm > petalwidthcm; 就波动程度来说, petallengthcm > petalwidthcm > sepallengthcm > sepalwidthcm; 就异常值来说, 只有sepalwidthcm中存在异常值. 

Python数据分析--Iris数据集实战

将鸢尾花的三种种类再加入到箱线图中:

sns.boxplot(x='attribute', y='data',hue='species', data=iris)

这样就很容易能够对比三个种类在四个属性中的表现状况:

除了sepalwidthcm属性外, 中位数在其他属性的三种花中均表现为: virginica > versicolour >  setosa

除了setosa种类外, 中位数在其他种类的四个属性中均表现为: sepallengthcm > petallengthcm > sepalwidthcm > petalwidthcm

Python数据分析--Iris数据集实战

下面将介绍一种更高级的四分位数展示方式: violinplot

3.2.5 violinplot

violinplot绘制的是琴图, 是箱线图与核密度图的结合体, 既可以展示四分位数, 又可以展示任意位置的密度.

sns.violinplot(x='attribute', y='data', hue='species', data=iris )

Python数据分析--Iris数据集实战

上图中具体细节显示不是很明显, 对于petalwidthcm都有些模糊了, 下面将拆分成四个小图, 另外为了和箱线图对比, 将箱线图也绘制出来.

#花萼长度
# sns.boxplot(x='species', y='sepallengthcm', data=df_iris)
# sns.violinplot(x='species', y='sepallengthcm', data=df_iris)
# plt.title('sepallengthcm data by species')
#花萼宽度
# sns.boxplot(x='species', y='sepalwidthcm', data=df_iris)
# sns.violinplot(x='species', y='sepalwidthcm', data=df_iris)
# plt.title('sepalwidthcm data by species')
#花瓣长度
# sns.boxplot(x='species', y='petallengthcm', data=df_iris)
# sns.violinplot(x='species', y='petallengthcm', data=df_iris)
# plt.title('petallengthcm data by species')
#花瓣宽度
sns.boxplot(x='species', y='petalwidthcm', data=df_iris)
sns.violinplot(x='species', y='petalwidthcm', data=df_iris)
plt.title('petalwidthcm data by species')

可以明显看出, 琴图中的白点就是中位数, 黑色矩形的上短边则是上四分位数q3, 黑色下短边则是下四分位数q1;  而贯穿矩形的黑线的上端点则代表最小非异常值, 下端点则代表最大非异常值; 黑色矩形外部形状则表示核概率密度估计.

Python数据分析--Iris数据集实战

最后介绍一种图形, 它能直接显示各个特征之间的不同关系

3.2.6 pairplot

#删除id特征, 绘制分布图
sns.pairplot(df_iris.drop('id', axis=1), hue='species')
#保存图片, 由于在jupyter notebook中太大, 不能一次截图
plt.savefig('pairplot.png')
plt.show()

Python数据分析--Iris数据集实战

综上, 花萼的长度, 花萼的宽度, 花瓣的长度, 花瓣的宽度与花的种类之间均存在一定的相关性, 且对于这三个种类的分布, satosa在任何一种分布中较其他两者集中; 就同一种花的平均水平来看, 其花萼的长度最长, 花瓣的宽度最短; 就同一属性的平均水平来看, 三种花在除了花萼的宽度外的属性中平均水平均表现为: virginica > versicolour >  setosa.

4. 构建模型

采用决策树分类算法.

from sklearn.model_selection import train_test_split
from sklearn.tree import decisiontreeclassifier

x = df_iris[['sepallengthcm','sepalwidthcm','petallengthcm','petalwidthcm']] y = df_iris['species'] #将数据按照8:2的比例随机分为训练集, 测试集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) #初始化决策树模型 dt = decisiontreeclassifier() #训练模型 dt.fit(x_train, y_train) #用测试集评估模型的好坏 dt.score(x_test, y_test)
0.9666666666666667

在测试集上准确率达到97%,也还不错, 此次没有对决策树模型设置参数, 如果参数设置好了, 想必准确率会更高.

 

参考: