直方图与密度图的绘制方法

目录 直方图 基础实现 hist()函数 扩展 色彩映射 双变量直方图 拟合分布曲线 密度图 基础实现 kdeplot()函数 扩展 多变量密度图 分组密度图 总结 直方图 直方图是一种常用的数据可视化工具,用于展示数据的分布情况。它将数据划分为若干个等宽的区间(也称为箱子或柱形),并计算每个区间内数据的频数或频率,

目录

直方图

基础实现

hist()函数

扩展

色彩映射

双变量直方图

拟合分布曲线

密度图

基础实现

kdeplot()函数

扩展

多变量密度图

分组密度图

 总结


直方图

        直方图是一种常用的数据可视化工具,用于展示数据的分布情况。它将数据划分为若干个等宽的区间(也称为箱子或柱形),并计算每个区间内数据的频数或频率,具体应用可参考:直方图在照片中的应用。直方图的作用如下:

  1. 揭示数据分布:直方图可帮助我们了解数据的分布形态和特征。通过观察直方图的形状、峰值、对称性等信息,我们可以获得关于数据集的直观认识。例如,直方图可以显示数据是集中在某个区间还是分散在整个范围内,是否存在异常值或离群点等。

  2. 发现数据的统计特征:通过直方图,我们可以观察数据的中心趋势、变异程度和偏斜程度等统计特征。例如,直方图的峰值位置可以反映数据的众数,直方图的宽度可以表示数据的分散程度。直方图还可以用于检测数据的偏斜性,例如正态分布通常具有对称的直方图。

  3. 比较不同数据集:直方图可以用于比较不同数据集之间的分布差异。通过将多个直方图放在一起进行观察,我们可以发现数据之间的相似性或差异性。这对于数据分析、探索性数据分析以及进行假设检验等都非常有用。

  4. 探索异常值和离群点:直方图可以帮助我们发现数据中的异常值或离群点。异常值通常表现为在直方图中与其他数据点明显不同的极端值。通过观察直方图,我们可以识别这些异常值,并进一步进行数据清洗或分析。

基础实现

        当使用Matplotlib绘制直方图时,你可以使用 matplotlib.pyplot.hist() 函数。

import numpy as np
import matplotlib.pyplot as plt

# 生成随机数据
np.random.seed(0)
data = np.random.randn(1000)  # 生成1000个服从标准正态分布的随机数

# 绘制直方图
plt.hist(data, bins=30, edgecolor='black')  # 使用30个柱形,并设置柱形边界颜色为黑色
plt.xlabel('Value')  # x轴标签
plt.ylabel('Frequency')  # y轴标签
plt.title('Histogram of Random Data')  # 图表标题
plt.grid(False)  # 显示网格线
plt.show()  # 显示图表

hist()函数

定义:

matplotlib.pyplot.hist(x, bins=None, range=None, density=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, \*, data=None, \*\*kwargs)

参数:

x : 待可视化处理的数据集
bins : 统计的区间分布划分,指定绘制柱形图的总个数;
range : 显示的区间
density : 显示概率密度,默认为false
histtype : 可选{‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’}之一,默认为bar,推荐使用默认配置,step使用的是梯状,stepfilled则会对梯状内部进行填充,效果与bar类似
align : 可选{‘left’, ‘mid’, ‘right’}之一,默认为’mid’,控制柱状图的水平分布,left或者right,会有部分空白区域,推荐使用默认
log : 默认为False,y坐标轴是否选择指数刻度,在数据分布的范围较大的时候,可以通过log指数刻度来缩小显示的范围。
stacked : 默认为False,是否为堆积状图

扩展

色彩映射

        hist函数返回值有3个,分别是:

  1. 频数数组(histogram):这是一个包含每个区间内数据的频数的一维数组。它表示了每个区间内数据出现的次数。

  2. 区间边界数组(bin edges):这是一个包含直方图的区间边界值的一维数组。它表示了直方图中每个区间的边界值。

  3. 图形对象(patches):这是一个包含绘制的直方图图形对象的列表。每个图形对象代表一个直方柱形。

        我们可以利用该特性实现色彩映射,完成数据可视化。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib
from matplotlib import colors


# 从 Google API 上下载暂存字体放到暂存文件夹下

!wget 'https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKtc-hinted.zip'
!mkdir /tmp/fonts
!unzip -o NotoSansCJKtc-hinted.zip -d /tmp/fonts/
!mv /tmp/fonts/NotoSansMonoCJKtc-Regular.otf /usr/share/fonts/truetype/NotoSansMonoCJKtc-Regular.otf -f
!rm -rf /tmp/fonts
!rm NotoSansCJKtc-hinted.zip

# 指定字体
import matplotlib.font_manager as font_manager
import matplotlib.pyplot as plt
 
font_dirs = ['/usr/share/fonts/truetype/']
font_files = font_manager.findSystemFonts(fontpaths=font_dirs)
 
for font_file in font_files:
  font_manager.fontManager.addfont(font_file)
 
plt.rcParams['font.family'] = "Noto Sans Mono CJK TC"


"""
随机数生成,自动生成正态分布的数据集
"""
np.random.seed(0)
data = np.random.randn(1000)


"""
n: 数组或数组列表,表明每一个bar区间的数量或者百分比
bins : 数组,bar的范围和bins参数含义一样
patches : 列表 或者列表的列表 图形对象
"""
n, bins, patches =plt.hist(data, bins=40)
percent = n / n.max()

# 将percent中的数据进行正则化,方便映射到colormap中

norm = colors.Normalize(percent.min(), percent.max())


#在循环中,percent是一个包含数值的列表,patches是一组图形对象(例如矩形或圆形)。循环的目的是为每个图形对象设置颜色。

#首先,通过zip(percent, patches)将percent和patches两个可迭代对象进行逐个配对。这样,thisfrac将依次等于percent中的每个数值,thispatch将依次等于patches中的每个图形对象。

#接下来,norm(thisfrac)将数值thisfrac进行归一化,使其范围在0到1之间。然后,plt.cm.viridis()函数将归一化后的数值映射到颜色空间中,返回对应的颜色。

#最后,thispatch.set_facecolor(color)将图形对象thispatch的填充颜色设置为变量color所代表的颜色。

for thisfrac, thispatch in zip(percent, patches):
    color = plt.cm.viridis(norm(thisfrac)) # plt.cm.viridis()是Matplotlib中的一个内置颜色映射(colormap),用于将数值映射到颜色空间
    thispatch.set_facecolor(color)



plt.xlabel("区间")
plt.ylabel("频率")
plt.title("频率分布图")
plt.show()

双变量直方图

        在基础实现中,我们实现了单变量直方图的绘制,实际中我们往往还需要进行双变量乃至多变量的相关性分析,此时使用直方图便可较为清晰地明确变量之间的关系,接下来以双变量直方图的绘制为例进行具体分析。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import colors
from matplotlib.ticker import PercentFormatter

import matplotlib.gridspec as gridspec

np.random.seed(0)
N = 1000
bins = 50

"""
生成为x,y随机数据
"""
x = np.random.randn(N)
y = x ** 2 + np.random.randn(N) + 5


fig = plt.figure(figsize=(10, 8))
# gridspec的用法,可以使图像横跨多个坐标
G = gridspec.GridSpec(2, 2) # 绘制一个2行2列的figure对象

#显示第一坐标系,其位置第一行,第一列(G[0, 0])
axes =fig.add_subplot(G[0, 0])
axes.hist(x, bins= bins)

#显示第二坐标系,其位置第一行,第二列(G[0, 1])
axes =fig.add_subplot(G[0, 1])
axes.hist(y, bins=bins)

#显示第三坐标系,其位置第二行整行(G[1, :])
axes =fig.add_subplot(G[1, :])
axes.hist2d(x,y, bins=bins)

plt.show()

        可见,此时 y 与 x^2 相关,直方图正确显示。

拟合分布曲线

        绘制直方图后,我们还可以选择是否对直方图的变化趋势进行曲线拟合,这样利于判断一些难以直观发现的变化趋势。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib


# 从 Google API 上下载暂存字体放到暂存文件夹下

!wget 'https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKtc-hinted.zip'
!mkdir /tmp/fonts
!unzip -o NotoSansCJKtc-hinted.zip -d /tmp/fonts/
!mv /tmp/fonts/NotoSansMonoCJKtc-Regular.otf /usr/share/fonts/truetype/NotoSansMonoCJKtc-Regular.otf -f
!rm -rf /tmp/fonts
!rm NotoSansCJKtc-hinted.zip

# 指定字体
import matplotlib.font_manager as font_manager
import matplotlib.pyplot as plt

font_dirs = ['/usr/share/fonts/truetype/']
font_files = font_manager.findSystemFonts(fontpaths=font_dirs)

for font_file in font_files:
  font_manager.fontManager.addfont(font_file)

plt.rcParams['font.family'] = "Noto Sans Mono CJK TC"


N = 50

data = np.random.randn(1000)

fig,ax = plt.subplots()

n, bins, patches = ax.hist(data, bins = N, density=True)

# 拟合分布曲线
ax.plot(bins[:N],n,'--') # bins[:N]为横坐标, n为纵坐标


plt.xlabel("区间")
plt.ylabel("频率")
plt.title("拟合直方图")
plt.show()

密度图

        密度图是一种数据可视化技术,用于显示连续变量的分布情况。它通过在二维平面上绘制数据点的密度来展示数据的分布情况,特别适用于大量数据的可视化。

基础实现

        常见的绘制密度图的方法为核密度估计(KDE),具体步骤为:KDE使用核函数对每个数据点周围的区域进行平滑,并估计该区域内数据点的密度。

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# 生成一些示例数据
np.random.seed(0)
data = np.random.randn(1000)

# 创建图形对象
plt.figure(figsize=(8, 6))

# 绘制密度图
sns.kdeplot(data, fill = True)

# 设置其他绘图参数
plt.xlabel('X-axis')
plt.ylabel('Density')
plt.title('Density Plot')

# 显示密度图
plt.show()

kdeplot()函数

定义:

seaborn.kdeplot(data, data2=None, shade=False, vertical=False, kernel="gau", bw="scott", gridsize=200, cut=3, clip=None, legend=True, cumulative=False, shade_lowest=True, cbar=False, cbar_ax=None, cbar_kws=None, ax=None)

参数:

  • data:  输入的数据,可以是一维数组、Series、DataFrame的列名或者二维数据。
  • data2(可选): 用于双变量密度估计的第二个变量数据,可以是一维数组、Series、DataFrame的列名或者二维数据。
  • fill(可选): 是否填充密度曲线下的区域,默认为False
  • vertical(可选): 是否将密度曲线绘制为垂直方向(默认为水平方向)。
  • kernel(可选): 核函数的类型,控制密度估计的平滑程度,默认为高斯核函数("gau")。
  • bw(可选): 带宽选择方法,用于调整密度估计的平滑程度,默认为"scott"方法。
  • gridsize(可选): 网格的大小,用于计算核密度估计,默认为200。
  • legend(可选): 是否显示图例,默认为True
  • cumulative(可选): 是否绘制累积密度图,默认为False
  • cbar(可选): 是否显示颜色条,默认为False

 

扩展

多变量密度图

       通过使用多变量核密度估计,可以绘制多变量密度图,以展示多个变量之间的联合分布情况。

import seaborn as sns

# 生成示例数据
data = sns.load_dataset("iris")

# 创建图形对象
plt.figure(figsize=(8, 6))

# 绘制多变量密度图
sns.kdeplot(data=data, x="sepal_length", y="sepal_width", hue="species", fill=True)

# 设置其他绘图参数
plt.xlabel('Sepal Length')
plt.ylabel('Sepal Width')
plt.title('Multivariate Density Plot')

# 显示密度图
plt.show()

        这个示例使用 seaborn 库的 kdeplot() 函数绘制了一张多变量密度图。它展示了鸢尾花数据集中萼片长度与萼片宽度之间的密度分布,并根据不同的鸢尾花种类进行了颜色编码。

分组密度图

        分组密度图用于比较不同组之间的数据分布情况。通过将不同组的数据分别绘制在同一张图上,可以直观地比较它们之间的密度差异。

import seaborn as sns

# 生成示例数据
data = sns.load_dataset("tips")

# 创建图形对象
plt.figure(figsize=(8, 6))

# 绘制分组密度图
sns.kdeplot(data=data, x="total_bill", hue="time", fill=True)

# 设置其他绘图参数
plt.xlabel('Total Bill')
plt.ylabel('Density')
plt.title('Grouped Density Plot')

# 显示密度图
plt.show()

         展示了不同用餐时间(午餐和晚餐)下的账单总额的密度分布,并使用颜色进行了区分。

 总结

        本次主要从 hist() 和 kdeplot() 两个函数具体学习了直方图与密度图的绘制,分别基于Matplotlib与Seaborn载入样例数据进行可视化,掌握了不少数据分析配图的小技巧。

知秋君
上一篇 2024-08-25 18:36
下一篇 2024-08-25 18:02

相关推荐