如何在Matplotlib上生成一系列直方图?

4
我希望生成下面显示的一系列直方图: enter image description here 上述可视化是在tensorflow中完成的,但我想在matplotlib上重现相同的可视化。
编辑: 使用@SpghttCd建议的plt.fill_between,我有以下代码:
colors=cm.OrRd_r(np.linspace(.2, .6, 10))
plt.figure()
x = np.arange(100)
for i in range(10):
    y = np.random.rand(100)
    plt.fill_between(x, y + 10-i, 10-i, 
                     facecolor=colors[i]
                     edgecolor='w')
plt.show()

这很好用,但是能否使用直方图代替连续的曲线?

你好,在此期间我意识到这种类型的图表被称为"ridgeline plot"。据我所知,它最好由R(https://github.com/clauswilke/ggridges)支持,但也有一个专门用于该类型图表的Python库,名为`joypy`(http://sbebo.github.io/blog/blog/2017/08/01/joypy/)。 - SpghttCd
1个回答

12

编辑:
像十月份评论中提到的那样,采用基于joypy的方法:

import pandas as pd
import joypy
import numpy as np

df = pd.DataFrame()
for i in range(0, 400, 20):
    df[i] = np.random.normal(i/410*5, size=30)
joypy.joyplot(df, overlap=2, colormap=cm.OrRd_r, linecolor='w', linewidth=.5)

在这里输入图片描述

为了更好地控制颜色,您可以定义一个颜色梯度函数,该函数接受分数索引和起始和停止颜色元组:

def color_gradient(x=0.0, start=(0, 0, 0), stop=(1, 1, 1)):
    r = np.interp(x, [0, 1], [start[0], stop[0]])
    g = np.interp(x, [0, 1], [start[1], stop[1]])
    b = np.interp(x, [0, 1], [start[2], stop[2]])
    return (r, g, b)

使用方法:

joypy.joyplot(df, overlap=2, colormap=lambda x: color_gradient(x, start=(.78, .25, .09), stop=(1.0, .64, .44)), linecolor='w', linewidth=.5)

具有不同起始和停止元组的示例:

enter image description here


原始答案:

您可以使用plt.fill_between迭代要绘制的数据数组,将颜色设置为某些渐变,并将线条颜色设置为白色:

创建一些示例数据:

import numpy as np
t = np.linspace(-1.6, 1.6, 11)
y = np.cos(t)**2
y2 = lambda : y + np.random.random(len(y))/5-.1

绘制这个系列:

import matplotlib.pyplot as plt

import matplotlib.cm as cm
colors = cm.OrRd_r(np.linspace(.2, .6, 10))

plt.figure()
for i in range(10):
    plt.fill_between(t+i, y2()+10-i/10, 10-i/10, facecolor = colors[i], edgecolor='w')

在此输入图片描述

如果您希望它更加适合您的示例,您可以考虑提供一些样本数据。

编辑:
正如我在下面评论中所说,我不确定您想要什么,或者您是否想要最好的解决方案。因此,在您的编辑中,这里有一个代码,它绘制了两个直方图的示例,以便它们更好地可比较:

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

N = 10
np.random.seed(42)

colors=cm.OrRd_r(np.linspace(.2, .6, N))

fig1 = plt.figure()
x = np.arange(100)
for i in range(10):
    y = np.random.rand(100)
    plt.fill_between(x, y + 10-i, 10-i, 
                     facecolor=colors[i],
                     edgecolor='w')

data = np.random.binomial(20, .3, (N, 100))

fig2, axs = plt.subplots(N, figsize=(10, 6))
for i, d in enumerate(data):
    axs[i].hist(d, range(20), color=colors[i], label=str(i))
fig2.legend(loc='upper center', ncol=5)


fig3, ax = plt.subplots(figsize=(10, 6))
ax.hist(data.T, range(20), color=colors, label=[str(i) for i in range(N)])
fig3.legend(loc='upper center', ncol=5)

这将导致以下图表:
  1. 您编辑的图表: enter image description here

  2. N 个直方图在 N 个子图中: enter image description here

  3. N 个直方图并排在一个图表中: enter image description here


谢谢,这正是我想要的。使用预先指定的区间,可以使用numpy直方图来实现吗? - MoneyBall
所以你想要条形图而不是fill_between吗?或者像上面建议的那样使用fill_between,但数据源是np.histogram的结果? - SpghttCd
是的,我正在尝试使用条形图。 - MoneyBall
说实话,我真的不太明白您想要实现什么。编辑器中生成的代码图表与您最初请求的有些不同。没有重叠,也没有x方向上的偏移... 不管怎样,我不知道您是否真的需要将几个图表分布到一个坐标系中。使用n个子图在一个图中绘制n个直方图会更好吗? - SpghttCd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接