条形图 也被称为柱形图、柱状图等 用于展示分类变量的分布情况。在条形图中 分类变量的每个类别用长条表示 高度表示数据该类别的出现频率。我们可以通过 seaborn 的 countplot 函数创建基本的频率条形图
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sb %matplotlib inline
其中%matplotlib inline 就可以在Note中直接画图表了
sb.countplot(data df, x cat_var )//若加分号 则图表绘制对象的信息就不会显示出来了
对于给出的示例 可以看出 Beta 类别频率最高 超过 100 次 然后是 Gamma 和 Alpha Delta 的频率最低 大约为 50。默认情况下 每个类别都用不同的颜色标注。当我们探索更多变量时 添加颜色标注可能会对建立这些类别之间的关联性有帮助。其他情况下 建议简化图表 将所有长条都用相同的颜色标注 可以减少不必要的干扰。我们可以使用 “color” 参数设置长条颜色
base_color sb.color_palette()[0] sb.countplot(data df, x cat_var , color base_color)
color_palette 返回一个 RGB 元组列表 每个元组由三个数字组成 分别对应红绿蓝通道值 这三个值确定一个颜色。在没有任何参数的情况下调用此函数会返回当前/默认的调色板 我们将默认调色板的第一个颜色设为所有长条的颜色。
对于条形图 我们可能想要执行的一个操作是以某种方式对数据进行排序。对于无序分类数据 一种常见操作是按照频率对数据排序。我们的数据是 pandas Dataframe 类型 因此我们可以使用各种 Dataframe 的方法来计算和得出排序方式 然后使用 “order” 参数设置排序方式
base_color sb.color_palette()[0] cat_order df[ cat_var ].value_counts().index sb.countplot(data df, x cat_var , color base_color, order cat_order)
对于有序分类数据 我们可能需要根据固有的变量顺序对长条排序。虽然我们也可以像上面的示例一样按照频率对各级别进行排序 但是我们通常更关心的是高频率的数值属于较高级别还是较低级别。在这种情况下 最佳的做法是将该列转换为有序类别 ordered category 数据类型。默认情况下 pandas 会将字符串数据读取为 object 类型 并按照看到唯一值的先后顺序绘制长条。通过将数据转换为 ordered 类型 类别的顺序将变成该特征的固有排序 不用在每次需要绘图时都指定 “order” 参数。
# 本方法要求 pandas 0.21 或更高版本 level_order [ Alpha , Beta , Gamma , Delta ] ordered_cat pd.api.types.CategoricalDtype(ordered True, categories level_order) df[ cat_var ] df[ cat_var ].astype(ordered_cat) ## 如果你的 pandas 为 0.20.3 或更低版本 请使用这种方法 # df[ cat_var ] df[ cat_var ].astype( category , ordered True, # categories level_order) base_color sb.color_palette()[0] sb.countplot(data df, x cat_var , color base_color)
如果你发现需要按照不同的顺序对有序分类数据排序 则可以通过设置 “order” 参数临时覆盖数据类型 如上所示。
#补充 如果数据是 pandas Series、一维 NumPy 数组或列表形式 你可以将其设为 countplot 函数的第一个参数 比如 Series 数据 data_var 就可以像下面这样绘制 sb.countplot(data_var) 如果有很多个分类级别 或者类别名称很长 那么刻度标记可能会紧挨在一起。一种解决方式是创建横向条形图。在横向条形图中 每个长条的长度 而不是高度 表示频率。在代码中 你可以在参数 y 上设置变量 而不是在参数 x 上设置变量 base_color sb.color_palette()[0] sb.countplot(data df, y cat_var , color base_color) 此外 你还可以使用 matplotlib 的 xticks 函数及其 rotation 参数更改绘制刻度标记的方向 与水平方向的逆时针夹角度数 base_color sb.color_palette()[0] sb.countplot(data df, x cat_var , color base_color) plt.xticks(rotation 90)绝对频率与相对频率
默认情况下 seaborn 的 countplot 函数将以绝对频率 即纯粹计数 汇总 和绘制数据。在某些情形下 你可能想要了解数据分布或者用在总体中所占的比例比较类别。在这种情形下 你需要用相对频率绘制数据 这时条形的高度表示数据在每个类别的占比 而不是绝对计数。
在条形图中用相对频率绘制数据的一种方式是 将坐标轴的刻度标签修改为比例的形式。底层数据不变 只是轴刻度会发生变化。
# get proportion taken by most common group for derivation
# of tick marks
n_points df.shape[0]
max_count df[ cat_var ].value_counts().max()
max_prop max_count / n_points
# generate tick mark locations and names
tick_props np.arange(0, max_prop, 0.05)
tick_names [ {:0.2f} .format(v) for v in tick_props]
# create the plot
base_color sb.color_palette()[0]
sb.countplot(data df, x cat_var , color base_color)
plt.yticks(tick_props * n_points, tick_names)
plt.ylabel( proportion )
注代码中tick_props * n_points是为了获取正确的刻度位置
xticks 和 yticks 函数不仅仅会旋转刻度标签的方向。你还可以获取和设置它们的位置及文字标签。第一个参数表示刻度位置 在此例中 刻度比例翻倍后变回计数比例。第二个参数表示刻度名称 在此例中 刻度比例的格式为精确到两位小数的字符串。
我还添加了 ylabel “proportion” 表明我们不再使用绝对计数 。
另外 你还可以在长条上使用文本注释标记相对频率 而不是以相对频率标尺绘制数据。这需要编写一个循环来遍历刻度位置和标签 并为每个长条添加一个文本元素。
# create the plot
base_color sb.color_palette()[0]
sb.countplot(data df, x cat_var , color base_color)
# add annotations
n_points df.shape[0]
cat_counts df[ cat_var ].value_counts()
locs, labels plt.xticks() # get the current tick locations and labels
# loop through each pair of locations and labels
for loc, label in zip(locs, labels):
# get the text property for the label to get the correct count
count cat_counts[label.get_text()]
pct_string {:0.1f}% .format(100*count/n_points)
# print the annotation just below the top of the bar
plt.text(loc, count-8, pct_string, ha center , color w )
我使用 .get_text() 方法获取类别名称 从而获取每个分类级别的计数。最后 我使用 text 函数 将 x 坐标、y 坐标和字符串作为该函数的三个主要参数传入 打印出每个百分比 。
条形图的一种有趣应用是可视化缺失数据。我们可以使用 pandas 的函数创建一个数据 其中包含每列缺失值的数量。
df.isna().sum()
如果我们想可视化这些缺失值的计数 应该如何做呢 我们可以将变量名当做一个分类变量的各个类别 创建条形图。然而 由于这些数据属于汇总统计后的形式 我们需要使用另一个绘制函数。Seaborn 的 barplot 函数旨在描述一个数值变量相对于另一个分类变量的直观比较 可用在此处。
na_counts df.isna().sum() base_color sb.color_palette()[0] sb.barplot(na_counts.index.values, na_counts, color base_color)
该函数的第一个参数为 x 值 列名称 第二个参数为 y 值 计数 。
一般而言 如果你的数据经过了汇总统计 但你依然想要绘制条形图 那么就可以用这个函数。但是如果数据尚未汇总 则使用 countplot 函数 这样就不需要进行额外的汇总统计工作。此外 在下节课讨论如何调整单变量图以绘制双变量数据时 你将在了解 barplot 的主要作用。



