明晰柱状图和直方图的区别
在众多的分析图表中,柱状图和直方图算是特别容易被混淆的两种图,因为它们在外形上非常相似。比如:
而实际上,它们所表达的含义和应用的场景却完全不同。
1. 概念
柱状图,是一种使用矩形条,对不同类别进行数值比较的统计图表。在柱状图上,分类变量的每个实体都被表示为一个矩形(通俗讲即为“柱子”),而数值则决定了柱子的高度。
直方图,又称质量分布图,用于表示数据的分布情况。一般用横轴表示数据区间,纵轴表示分布情况,柱子越高,则落在该区间的数量越大。
从概念上看,同样是柱子,含义差别就很大,一个表示的是每种分类的数值,一个表示的则是某个区间内数据的数量。一个是值,一个是量;一个是比较大小情况,一个是看分布情况;一个是离散的,一个是连续的。
从它们的概念上就能看出会用在完全不一样的分析场景中。
2. 应用场景
从应用场景上更容易区分两种图形的不同点。
2.1. 适用柱状图而不适用直方图
以下适用柱状图的分析场景,用直方图很难表达:
- 比较不同类别的数据,例如比较不同产品的销售量。直方图主要用于展示数据的分布情况,而不适合比较不同类别的数据。
- 显示数据的变化趋势,例如展示某个产品在不同时间段的销售额。柱状图可以将不同时间段的数据以不同的柱子展示,而直方图无法有效地表示时间变化的趋势。
- 比较不同组织或地区的数据,例如比较不同城市的人口数量。柱状图可以将不同组织或地区的数据以不同的柱子展示,而直方图无法有效地进行比较。
- 可视化数据的分布情况,例如展示不同年龄段的人口比例。柱状图可以将不同年龄段的数据以不同的柱子展示,而直方图主要用于表示连续变量的分布情况,不适合表示离散变量的比例。
2.2. 适用直方图而不适用柱状图
以下适用直方图的分析场景,用柱状图很难表达:
- 表示连续变量的分布情况,例如展示一个班级学生的身高分布。柱状图适用于离散变量,不能有效地表示连续变量的分布情况。
- 分析数据的频率分布,例如统计一个城市每天的交通拥堵指数。直方图可以显示不同数值范围的频率分布情况,而柱状图只能显示各个类别的计数。
- 探索数据的异常值,例如查看一组温度数据中是否存在异常高或低的值。直方图可以通过观察数据的分布情况来检测异常值,而柱状图无法提供相同的信息。
- 比较不同组的数据分布,例如比较男性和女性的体重分布。直方图可以将不同组的数据分布在同一图表中进行比较,而柱状图只能比较同一组的不同类别的数据。
3. 分析示例
最后,通过实际的数据来演示两种图形在实战中的区别。基于用同样的数据,绘制两种图形,来直观的理解在实际分析场景中如何选择这两类图形。
接下来使用王者荣耀KPL2023春季赛的相关数据进行分析,绘制柱状图和直方图。数据来源王者荣耀官网,可以从下面的网址中下载:databook.top/wzry/2023-s…
其中包含3个数据文件:
- league-2023春季赛.csv 战队数据
- player-2023春季赛.csv 选手数据
- hero-2023春季赛.csv 英雄数据
3.1. 选手参赛场次的分析
读取数据:
import pandas as pd
df = pd.read_csv("d:/share/data/player-2023春季赛.csv")
data = df.loc[:, ["选手", "比赛场次"]]
data
一共有125条数据。
根据每个选手的比赛场次,绘制柱状图。
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
names = data["选手"].tolist()
ax.bar(names, data["比赛场次"])
ax.set_xticklabels([])
ax.set_title("各个选手的比赛场次")
图中每个柱子表示的是每个选手的比赛场次。横轴每个刻度就是一个选手。
根据每个选手的比赛场次,绘制直方图。
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.hist(data["比赛场次"], bins=10)
ax.set_title("选手的比赛场次分布情况")
这里的横轴表示选手参加的场次,相当于柱状图的纵轴的含义。纵轴是选手的人数,柱子的高度表示在区间范围内的选手个数。通过直方图,可以了解到的信息是
- 参加
1~10
场比赛的选手最多 - 参加
60
场以上的选手也不少,说明各个战队的首发阵容还是比较稳定的。
绘制直方图的代码中,我们设置了 bins=10
,就是将比赛场次分为10个区间。上面的数据中,最小的比赛场次1
,最大比赛场次91
,所以各个区间范围是:1~10
,10~19
。。。82~91
。
3.2. 各个战队的胜率分析
读取数据:
df = pd.read_csv("d:/share/data/league-2023春季赛.csv")
data = df.loc[:, ["战队", "胜率"]]
data["胜率"] = data["胜率"].str.replace("%", "")
data["胜率"] = data["胜率"].astype("float")
data
根据每个战队的胜率,绘制柱状图。
import matplotlib.ticker as mticker
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
names = data["战队"].tolist()
ax.bar(names, data["胜率"])
plt.xticks(rotation=90)
yticks = ax.get_yticks().tolist()
ax.yaxis.set_major_locator(mticker.FixedLocator(yticks))
ax.set_yticklabels(["{}%".format(x) for x in yticks])
ax.set_title("各个战队的胜率")
从分析结果可以看出:
- 大部分战队的胜率差不多
- 战队是按照名次从左到右排列的,胜率基本是随着名次的下降也在缓慢下降的
根据每个战队的胜率,绘制直方图。
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.hist(data["胜率"], bins=5)
xticks = ax.get_xticks().tolist()
ax.xaxis.set_major_locator(mticker.FixedLocator(xticks))
ax.set_xticklabels(["{}%".format(x) for x in xticks])
ax.set_title("所有战队胜率分布情况")
从直方图的结果可以看出,大部分战队的胜率在 40%~60%
左右。
3.3. 分析总结
从上面两个分析场景中,可以看出,
- 同样的数据,既可以绘制柱状图,也可以绘制直方图
- 两种图形展示的分析结果,含义完全不同
- 第一个分析示例(选手参赛场次的分析)中,更适合用直方图来分析。
- 因为选手比较多,用柱状图看每个选手的比赛场次意义不大
- 用直方图看选手比赛场次的分布更有意义。
- 第二个分析示例(各个战队的胜率分析)中,更适合用柱状图来分析。
- 用柱状图的话,不仅可以看到胜率情况,可以看到胜率和排名的关系
- 数据量太小,用直方图看分布意义不大
转载自:https://juejin.cn/post/7252522702484111415