matplotlib:使用seaborn.heatmap

时间:2019-04-12 07:50:53

标签: python matplotlib histogram seaborn heatmap

动机:

我正在尝试可视化许多n维矢量的数据集(假设我有10k个矢量,n = 300维)。我想做的是为n个维度中的每个维度计算直方图,并将其绘制为bins * n热图中的一条直线。

到目前为止,我已经知道了:

import numpy as np
import matplotlib
from matplotlib import pyplot as plt
%matplotlib inline
import seaborn as sns

# sample data:
vectors = np.random.randn(10000, 300) + np.random.randn(300)

def ndhist(vectors, bins=500):
    limits = (vectors.min(), vectors.max())
    hists = []
    dims = vectors.shape[1]
    for dim in range(dims):
        h, bins = np.histogram(vectors[:, dim], bins=bins, range=limits)
        hists.append(h)
    hists = np.array(hists)
    fig = plt.figure(figsize=(16, 9))
    sns.heatmap(hists)
    axes = fig.gca()
    axes.set(ylabel='dimensions', xlabel='values')
    print(dims)
    print(limits)

ndhist(vectors)

这将产生以下输出:

300
(-6.538069472429366, 6.52159540162285)

bad axes ticks

问题/问题:

如何更改轴刻度?

  • 对于y轴,我想简单地将其更改为matplotlib的默认值,因此它会选择类似0, 50, 100, ..., 250299300的奖励点)
  • 对于x轴,我想将显示的bin索引转换为bin(左)边界,然后,如上所述,我想将其更改回matplotlib的默认选择,例如“ nice” -5, -2.5, 0, 2.5, 5(还包括实际限制-6.538, 6.522的奖励积分)

自己的解决方案尝试:

我已经尝试了很多类似以下的事情:

def ndhist_axlabels(vectors, bins=500):
    limits = (vectors.min(), vectors.max())
    hists = []
    dims = vectors.shape[1]
    for dim in range(dims):
        h, bins = np.histogram(vectors[:, dim], bins=bins, range=limits)
        hists.append(h)
    hists = np.array(hists)
    fig = plt.figure(figsize=(16, 9))
    sns.heatmap(hists, yticklabels=False, xticklabels=False)
    axes = fig.gca()
    axes.set(ylabel='dimensions', xlabel='values')
    #plt.xticks(np.linspace(*limits, len(bins)), bins)
    plt.xticks(range(len(bins)), bins)
    axes.xaxis.set_major_locator(matplotlib.ticker.AutoLocator())
    plt.yticks(range(dims+1), range(dims+1))
    axes.yaxis.set_major_locator(matplotlib.ticker.AutoLocator())
    print(dims)
    print(limits)

ndhist_axlabels(vectors)

even worse axes ticks

但是,如您所见,轴标签非常错误。我的猜测是,范围或限制存储在原始轴的某个位置,但是在切换回AutoLocator时丢失了。将不胜感激朝着正确方向前进。

3 个答案:

答案 0 :(得分:1)

也许您想得太多了。要绘制图像数据,可以使用imshow并免费获得刻度和格式。

import numpy as np
from matplotlib import pyplot as plt

# sample data:
vectors = np.random.randn(10000, 300) + np.random.randn(300)

def ndhist(vectors, bins=500):
    limits = (vectors.min(), vectors.max())
    hists = []
    dims = vectors.shape[1]

    for dim in range(dims):
        h, _ = np.histogram(vectors[:, dim], bins=bins, range=limits)
        hists.append(h)
    hists = np.array(hists)

    fig, ax = plt.subplots(figsize=(16, 9))

    extent = [limits[0], limits[-1], hists.shape[0]-0.5, -0.5]  
    im = ax.imshow(hists, extent=extent, aspect="auto")
    fig.colorbar(im)

    ax.set(ylabel='dimensions', xlabel='values')

ndhist(vectors)
plt.show()

enter image description here

答案 1 :(得分:0)

如果您阅读docs,则会注意到xticklabels / yticklabels参数是重载的,因此,如果您提供整数而不是字符串,它将解释该参数设置为xtickevery / ytickevery,并且仅在相应位置放置刻度。因此,根据您的情况,seaborn.heatmap(hists, yticklabels=50)解决了您的y轴问题。

enter image description here

关于您的xtick标签,我只明确提供它们:

xtickevery = 50 
xticklabels = ['{:.1f}'.format(b) if ii%xtickevery == 0 else '' for ii, b in enumerate(bins)]
sns.heatmap(hists, yticklabels=50, xticklabels=xticklabels)

enter image description here

答案 2 :(得分:0)

最后提出了一个目前适用于我的版本,并基于一些简单的线性映射使用了using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { string str0 = reader[0].ToString(); string str1 = reader[1].ToString(); string str2 = reader[2].ToString(); } } ...

AutoLocator

ndim hist

感谢Paul his answer给了我这个主意。

如果有一个更简单或更优雅的解决方案,我仍然会感兴趣。