数据可视化
在完成数据清理后,对数据进行可视化可以更佳清晰、直观地了解数据的情况。利用 pandas 进行数据分析时,数据可视化可以借助 pandas 自带的绘图功能或 seaborn 模块进行。
plot 绘图
pandas 自带 plot 绘图功能,但是需要依赖 matplotlib 实现,需要先引入 matplotlib 模块,通常引入的写法为:
import matplotlib.pyplot as plt
在 notebook 中直接显示图像:
%matplotlib inline
正常显示中文和负号的设置:
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用于正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用于正常显示负号
基本方法
pandas 中基本绘图的方式为 ser.plot()
/ df.plot()
,默认图形为折线图,默认将行索引作为 x 轴,列索引作为 y 轴,其主要参数如下:
参数 | 说明 |
---|---|
kind | 修改图表类型 |
x | 修改 x 轴 |
y | 修改 y 轴 |
alpha | 调整不透明度 |
linewidth | 修改线条粗细 |
如果要使用其他图表,如柱状图,既可以修改 kind='bar
参数,也可以通过类似属性的方式调用 df.plot.bar()
柱状图
pandas 中 plot 方法需要先将数据进行分组聚合统计后,然后再绘制图像,例如了解男女生存人数的分布,需要先统计男女生存人数情况,然后生成图表:
sex_survived = df.groupby('Sex')['Survived'].sum() # 根据性别分组统计生存人数
sex_survived.plot.bar() # 生成柱状图
上面的柱状图根据分组后的 Series 生成,只显示生存人数一个结果,如要需要同时展示生存和死亡人数,则需要根据一个列索引为生存、死亡情况的 DataFrame 来生成:
sex_survived = df.groupby('Sex')['Survived'].value_counts()
sex_survived.unstack().plot.bar() # 需要让 Survived 的值成为列索引,使用 unstack 方法
plt.title('Sruvived_conunt') # 添加图表标题
plt.ylabel('count') # 添加 y 轴注释
tips:使用 value_counts()
方法可以快速分别统计出生存和死亡的人数。
上述代码生成的图像,生存和死亡的人数分别显示为两个柱,如果想让生存和死亡人数叠加在一个柱,可以使用 stacked=True
参数,这样即可以了解男女的总人数情况,也可以了解各自生存和死亡人数的情况:
sex_survived.unstack().plot.bar(stacked=True)
泰坦尼克号不同仓位等级的人生存和死亡人员的分布情况也同样根据上面的方法可以画出柱状图:
fare_survived = df.groupby(['Pclass'])['Survived'].value_counts()
fare_survived.unstack().plot.bar()
折线图
使用 plot()
可以生成折线图。用折线图展示不同票价的人生存和死亡人数分布情况,同样也是先对数据进行分组,然后再生成图表:
fare_survived = df.groupby('Fare')['Survived'].value_counts()
fare_survived.unstack().plot()
直方图
plot.hist(bins=n)
可以生成直方图,其中 bins
参数用于控制分箱的数量。对于年龄等连续型的变量,用直方图可以很快了解其分布情况。
在泰坦尼克号数据集中,要获取不同年龄的人生存与死亡的分布情况,可以分别用索引获取生存的人的年龄数据、死亡的人的年龄数据,分别绘图进行叠加:
df.loc[df.Survived==0, 'Age'].plot.hist(alpha=0.5) # 为了使叠加后的图能看清,需要设置不透明度
df.loc[df.Survived==1, 'Age'].plot.hist(alpha=0.5)
但是上述方法需要进行多次索引,较为麻烦,且是将多张图像叠加在一个画布上,容易出现问题。如果要直接生成直方图,需要先对数据进行处理:
survived_age = df.set_index('Survived', append=True)['Age'].unstack()
survived_age.plot.hist(alpha=0.5)
密度图
密度图反映数据的密度分布情况,plot.kde()
可以生成密度图,用法和直方图有点类似。
展示不同仓位等级的人年龄分布情况,类似于上例中的直方图,需要先对数据进行整理,然后生成图像:
pclass_age= df.set_index('Pclass', append=True)['Age'].unstack()
pclass_age.plot.kde()
seaborn
seaborn 基于 matplotlib 封装而来,相较于 pandas 自带的绘图,无需对数据进行分组等处理,绘图风格上也存在一些差异。seaborn 通常引入的写法:
import seaborn as sns
以下将对上面的图像使用 seaborn 重新生成一遍,以对比两者的区别
柱状图对比
泰坦尼克号男女生存人数情况:
sns.barplot(df, x='Sex', y='Survived', estimator='sum', errorbar=None)
与 pandas 自带的 plot 方法对比可以发现,使用 seaborn 无需先对数据进行分组统计,可以直接把需要统计的信息以参数的形式传给 seaborn 的方法。
seaborn 中还有专门用于分类计数的图表 countplot,可以实现类似于 value_counts()
的效果,在本题中可以直接用于生成男女的生存和死亡人数情况、不同船舱等级的生存和死亡人数情况,使用该方法可以大大简化绘图的过程。
男女的生存和死亡人数情况:
sns.countplot(df, x='Sex', hue='Survived')
不同船舱等级的生存和死亡人数情况:
sns.countplot(df, x='Pclass', hue='Survived')
直方图对比
用 seaborn 绘制直方图使用 sns.histplot()
方法。该方法同样也无需对数据进行索引,直接将需要用到的数据以参数的形式传入函数即可,例如展示不同年龄的人生存与死亡的情况:
sns.histplot(data=df, x='Age', hue='Survived', alpha=0.3)
默认分的组数太多,通过 bins
参数可以调整分组的数量:
sns.histplot(data=df, x='Age', hue='Survived', alpha=0.3, bins=5)
密度图对比
sns.kdeplot()
用于绘制密度图。在泰坦尼克号案例总,用于展示不同仓位等级的人年龄分布情况:
sns.kdeplot(df, x='Age', hue='Pclass')
可以发现,默认绘制的密度图 y 轴坐标与 pandas 直接绘图存在差异,主要原因为 seaborn 默认 3 个曲线密度之和为 1,而不是每个曲线密度为 1,可以通过 common_norm
参数进行调整:
sns.kdeplot(df, x='Age', hue='Pclass', common_norm=False)
调整后生成的图像 y 轴与 pandas 的 plot 绘图结果也一致。
总结
将数据进行可视化处理可以方便我们更佳清晰、直观地了解数据的情况。pandas 常用的可视化方法为通过默认的 plot 方法或使用 seaborn 模块:
- plot 方法需要绘图前先对原始数据进行处理(分组聚合、索引等),然后根据处理后的对象生成相应的图像;
- seaborn 模块使用更佳简单,无需对原始数据进行处理,直接通过参数的形式传入相应的数据即可绘制图表。