使用 matplotlib 在一个子图中绘制来自 pandas DataFrame 的两个直方图

Posted

技术标签:

【中文标题】使用 matplotlib 在一个子图中绘制来自 pandas DataFrame 的两个直方图【英文标题】:Plotting two histograms from a pandas DataFrame in one subplot using matplotlib 【发布时间】:2019-01-15 20:49:29 【问题描述】:

我有一个如下所示的 pandas 数据框:

df = pd.DataFrame( 'a_wood' : np.random.randn(100),
                 'a_grassland' : np.random.randn(100),
                 'a_settlement' : np.random.randn(100),
                 'b_wood' : np.random.randn(100),
                 'b_grassland' : np.random.randn(100),
                  'b_settlement' : np.random.randn(100))

我想在一个子图中使用每个数据帧标题创建此数据的直方图。

fig, ax = plt.subplots(2, 3, sharex='col', sharey='row')

m=0
for i in range(2):
    for j in range(3):

        df.hist(column = df.columns[m], bins = 12, ax=ax[i,j], figsize=(20, 18))
        m+=1

为此,之前的代码完美运行,但现在我想将眼睛 a 和 b 标题(例如“a_woods”和“b-woods”)组合到一个子图中,这样就只有三个直方图。我尝试将两列分配给df.columns[[m,m+3]],但这不起作用。我还有一个索引列,其中包含像“day_1”这样的字符串,我希望它位于 x 轴上。有人可以帮我吗?

这是我走了多远。

【问题讨论】:

【参考方案1】:

我不知道我是否正确理解了你的问题,但这样的事情可以结合情节。您可能想尝试一下 alpha 并更改标题。

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

df = pd.DataFrame('a_wood'       : np.random.randn(100),
                   'a_grassland'  : np.random.randn(100),
                   'a_settlement' : np.random.randn(100),
                   'b_wood'       : np.random.randn(100),
                   'b_grassland'  : np.random.randn(100),
                   'b_settlement' : np.random.randn(100))

fig, ax = plt.subplots(1, 3, sharex='col', sharey='row', figsize=(20, 18))
n = 3
n_bins = 12

for i in range(n):
    min_value = df.iloc[:,[i,i+n]].min().min() #Get minimum value of column pairs, e.g. column 0 (a_wood) and column 3 (b_wood)
    max_value = df.iloc[:,[i,i+n]].max().max() #Get maximum value of column pairs
    bins = np.linspace(min_value, max_value, n_bins) #Create bins of equal size between min_value and max_value
    
    df.hist(column=df.columns[i], bins=bins, ax=ax[i], alpha=0.5, color='red')
    df.hist(column=df.columns[i+n], bins=bins, ax=ax[i], alpha=0.5, color='blue')
    ax[i].set_title(df.columns[i][2:])

要将它们绘制在彼此旁边,试试这个:

#We do not have to specify the bins in this example
fig, ax = plt.subplots(1, 3, sharex='col', sharey='row', figsize=(20, 18))

n = 3
colors = ['red', 'blue']

axes = ax.flatten()
for i,j in zip(range(n), axes):
    j.hist([df.iloc[:,i], df.iloc[:,i+n]], bins=12, color=colors)
    j.set_title(df.columns[i][2:])

【讨论】:

【参考方案2】:

您想要遍历每一列并在直方图中绘制其数据的东西,对吧? 我可以建议您进行一些修改,以便在以后的代码中重复使用,在给出代码之前,有一些有用的提示很有帮助,

    必须知道,数据框具有可用于循环的属性,例如,属性 .columns 具有列列表 另外,在绘图时,我注意到直接使用网格上的坐标不会让您的代码具有适应性,因此您需要“展平”您的网格坐标,因此使用ax.ravel() 来实现这一点。李> enumerate() 在循环对象时总是有用的,同时使第 i 个元素及其索引可用。 刚开始理解 python 中的子图很棘手,因此阅读其他人的代码确实很有帮助,我强烈建议您查看 scikit 函数示例中的图(它很有帮助)

这是我的代码建议:

fig, ax = plt.subplots(1, 3, sharex='col', sharey='row', figsize=(12,7))
ax = ax.ravel() 
# this method helps you to go from a 2x3 array coordinates to 
# 1x6 array, it will be helpful to use as below

for idx in range(3):
    ax[idx].hist(df.iloc[:,idx], bins=12, alpha=0.5)
    ax[idx].hist(df.iloc[:,idx+3], bins=12, alpha=0.5)
    ax[idx].set_title(df.columns[idx]+' with '+df.columns[idx+3])
    ax[idx].legend(loc='upper left')

我希望这对您有所帮助,如果您需要更多详细信息,请随时问我问题:)

注意:重新使用 Alex 的答案来编辑我的答案。另请查看matplotlib documentation 了解更多详情。在这种特定情况下,第 3 点不再相关。

【讨论】:

以上是关于使用 matplotlib 在一个子图中绘制来自 pandas DataFrame 的两个直方图的主要内容,如果未能解决你的问题,请参考以下文章

Matplotlib 在一张图中绘制多个条形图

python使用matplotlib可视化subplots绘制子图自定义几行几列子图,如果M行N列,那么最终包含M*N个子图在指定的子图中添加可视化结果

如何使用 matplotlib 创建子图的大图?

Matplotlib 绘制直方图、散点图

如何在 Python matplotlib 子图中显示图例

在 matplotlib 图中绘制平滑曲线