【问题标题】:Plotting multiple overlapped histogram with pandas用熊猫绘制多个重叠直方图
【发布时间】:2019-08-19 03:42:09
【问题描述】:

我有两个不同的数据框,每个数据框有 19 个变量,我正在用每个变量的直方图绘制一个多重图,如下所示:

fig, ax = plt.subplots(figsize=(19,10), dpi=50)
dataframe1.hist(ax=ax, layout=(3,7), alpha=0.5)

fig, ax = plt.subplots(figsize=(19,10), dpi=50)
dataframe2.hist(ax=ax, layout=(3,7), alpha=0.5)

这会生成两张图像,里面有 19 个直方图。我想尝试的是在同一个子图中只绘制一个具有共享直方图的图像。

我试过这个:

fig, ax = plt.subplots(figsize=(19,10), dpi=50)
dataframe1.hist(ax=ax, layout=(3,7), alpha=0.5, label='x')
dataframe2.hist(ax=ax, layout=(3,7), alpha=0.5, label='y', color='red')

但它只画了最后一张。 这是一个类似的例子:Plot two histograms at the same time with matplotlib 但我如何将它应用到两个我的 19 个子图中?

欢迎任何想法,提前谢谢!

P.S:我目前正在使用带有 %matplotlib notebook 选项的 Jupyter Notebooks

【问题讨论】:

  • 我理解正确,您想在同一组轴上显示 19 个 直方图?
  • 我刚刚添加了一张图片。我希望每个子图有 2 个直方图而不是 1 个。感谢您的理解!

标签: python pandas matplotlib


【解决方案1】:

您的问题是您在您的 plt.subplots 调用中只创建了一个 Axes 对象,而您实际上需要 21 (3x7)。由于提供的子图数量与请求的子图数量不匹配,pandas 会创建新的子图。因为这种情况发生了两次,所以您只能看到第二组直方图。

您可以完全忽略对subplots 的调用,让 pandas 完成所有工作。对hist 的调用会返回所有需要的子图,然后可以在对hist 的第二次调用中使用。

编辑

我意识到,如果所需绘图的数量实际上不等于网格单元的数量(在本例中为 3x9=21),则您必须准确传递您实际想要绘制的子图数量(在此案例 19)。但是,对 df.hist 的调用会为每个网格单元(即 21 个)返回一个子图,并且显然隐藏了未使用的子图。因此,您只需将所有返回的子图的一个子集传递给对hist 的第二次调用。最简单的方法是将子图的二维数组转换为一维数组,然后对该数组进行切片,例如使用 `axes.ravel()[:19]。我相应地编辑了代码:

import numpy as np
from matplotlib import pyplot as plt
import pandas as pd

length=19

loc = np.random.randint(0,50,size=length)
scale = np.random.rand(length)*10
dist = np.random.normal(loc=loc, scale=scale, size=(100,length))
df1 = pd.DataFrame(data=list(dist))


axes = df1.hist(layout=(3,7), alpha=0.5, label='x')

loc = np.random.randint(0,50,size=length)
scale = np.random.rand(length)*10
dist = np.random.normal(loc=loc, scale=scale, size=(100,length))
df2 = pd.DataFrame(data=list(dist))

df2.hist(ax=axes.ravel()[:length], layout=(3,7), alpha=0.5, label='x',color='r')

plt.show()

这会产生如下输出:

【讨论】:

  • 我认为您的意思是 ax=axes 而不是 ax=res
  • @ason​​gtoruin 你是对的。感谢您的帮助,我会在代码中修复它。
  • 谢谢!这正是我所需要的,但 x 标签是 45 或 90 度。我尝试过plt.set_xticklabels(rotation=90) 之类的方法,但没有成功。您知道如何进行此更改吗?
  • @BrunoAmbrozio pandas.hist 有内置关键字。例如xrot=45 将所有 xlabels 逆时针旋转 45 度。请注意,旋转刻度标签可能会使它们与相邻的子图重叠,因此您可能需要在脚本末尾添加额外的 plt.gcf().tight_layout()(但在 plt.show() 之前)。
  • @BrunoAmbrozio 如果您不想使用pandas.hist 功能,则必须分别为每个子图设置旋转角度。参见例如this post(标题为“面向对象”的部分)如何做到这一点。
【解决方案2】:

当您调用subplots 时,您可以指定所需的行数和列数。在您的情况下,您需要 3 行和 7 列。但是,.plot 会因为有 21 个轴但只有 19 个轴可以从您的数据框中绘制而感到恼火。因此,我们将把轴展平成一个列表并转换为一个列表,这将允许我们通过.pop()同时从图形和轴集中删除最后两个轴。

fig, axes = plt.subplots(figsize=(19,10), dpi=50, nrows=3, ncols=7)
flat_axes = list(axes.reshape(-1))
fig.delaxes(flat_axes.pop(-1))
fig.delaxes(flat_axes.pop(-1))

dataframe1.hist(ax=flat_axes, alpha=0.5, label='x')
dataframe2.hist(ax=flat_axes, alpha=0.5, label='x',color='r')

【讨论】:

    猜你喜欢
    • 2018-07-05
    • 1970-01-01
    • 2017-09-24
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多