Matplotlib和Seaborn之直方图

直方图

直方图用来绘制数字变量的分布情况。它是条形图的定量版本。但是,我们不再为每个独特数字值绘制一个长条,而是将值分成连续的分箱,并针对每个分箱绘制一个长条,用于描绘相关数字。例如,使用 matplotlib 的 hist 函数的默认设置:

plt.hist(data = df, x = 'num_var')

image.png

可以看出,在最左侧的分箱(约为 0 到 2.5 之间)中有 8 个数据点,在相邻分箱(约为 2.5 到 5 之间)中有 9 个数据点。总体来说,可以看出是一个双峰分布。直方图中的长条直接相连,而条形图中的长条是分开的,表明在直方图中数据的值处在连续范围内。如果某个数据值位于分箱边缘,则属于右侧分箱。例外情况是最右侧的分箱边缘,将上限的值放入最右侧的分箱内(上限的左侧)。

默认情况下,hist 函数会根据值的范围将数据分成 10 个分箱。在几乎所有情况下,我们都需要更改这一设置。通常,只有 10 个分箱太少了,无法了解数据的分布情况。并且默认的刻度并没有采用很容易解释分箱范围的近似值。如果在上述示例中,将“约为 0 到 2.5 之间”说成“0 到 2.5 之间”并将“约为 2.5 到 5 之间”说成“2.5 到 5 之间”,是不是更方便?

你可以使用描述统计学(例如通过 df['num_var'].describe())估测什么样的分箱下限和分箱上限比较合适。可以使用 numpy 的 arange 函数设置这些分箱边缘:

bin_edges = np.arange(0, df['num_var'].max()+1, 1)
plt.hist(data = df, x = 'num_var', bins = bin_edges)

arange 的第一个参数是最左侧的分箱边缘,第二个参数是上限,第三个参数是分箱宽度。注意,即使我在第二个参数中指定了“max”值,我添加了“+1”(分箱宽度)。这是因为 arange 将仅返回完全小于上限的值。加上“+1”可有效地确保左右侧的分箱边缘至少是最大数据值,以便所有数据点都能绘制出来。最左侧的分箱设为硬编码的值,以便获得可解释的值,当然你也可以使用 numpy 的 around 等函数以程序方式达到这种效果。

image.png

在创建直方图时,有必要尝试不同的分箱宽度,看看哪个宽度最能表示数据。如果分箱太多,可能会发现太多噪点,干扰我们发现数据蕴含的规律。如果分箱太少,则根本无法看出真正的规律。

plt.figure(figsize = [10, 5]) # larger figure size for subplots

# histogram on left, example of too-large bin size
plt.subplot(1, 2, 1) # 1 row, 2 cols, subplot 1
bin_edges = np.arange(0, df['num_var'].max()+4, 4)
plt.hist(data = df, x = 'num_var', bins = bin_edges)

# histogram on right, example of too-small bin size
plt.subplot(1, 2, 2) # 1 row, 2 cols, subplot 2
bin_edges = np.arange(0, df['num_var'].max()+1/4, 1/4)
plt.hist(data = df, x = 'num_var', bins = bin_edges)

该示例通过 subplot 函数将两个图形并排地放到一起,函数的参数指定了有效子图的行数、列数和索引。figure() 函数在调用时传入了 "figsize" 参数,以便我们能够绘制更大的图形并包含多个子图。

image.png

替代方法

seaborn 函数 distplot 也可以用于绘制直方图,并且与其他单变量绘图函数集成到一起。

sb.distplot(df['num_var'])

注意,第一个参数必须是 Series 或数组,其中包含要绘制的数据点,而不是指定数据来源和列。

image.png

distplot 函数具有指定直方图分箱的内置规则,默认情况下,会在数据上方绘制一个 (KDE) 核密度估计。纵轴基于 KDE,而不是直方图:长条的高度之和不一定等于 1,但是曲线下方的面积应该等于 1。如果你想详细了解 KDE,请参阅这节课末尾的补充内容。

虽然默认的 distplot 分箱尺寸可能比固定的 .hist = 10 更合适,但是你依然需要进行调整,使分箱尺寸等于四舍五入的值。你可以使用其他参数设置绘制直方图并像之前一样指定分箱:

bin_edges = np.arange(0, df['num_var'].max()+1, 1)
sb.distplot(df['num_var'], bins = bin_edges, kde = False,
            hist_kws = {'alpha' : 1})

alpha(透明度)设置必须当做字典与 "hist_kws" 关联,因为还有其他底层绘图函数(例如 KDE)具有自己的可选关键字参数。

image.png

上述代码的结果和上述分箱宽度为 1 的直方图完全一样。纵轴的单位也以计数的形式出现了。

总之,如果你只想了解数据的直方图分布情况,而不是 distplot 提供的额外信息,则为了简便,建议只使用 Matplotlib 的 hist 函数。另一方面,如果你想快速了解如何为直方图选择代表性的分箱尺寸,建议在自定义之前,先快速查看下基本的 distplot

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

推荐阅读更多精彩内容