【问题标题】:Matplotlib stacked histogram using `scatter_matrix` on pandas dataframeMatplotlib 在 pandas 数据帧上使用 `scatter_matrix` 堆叠直方图
【发布时间】:2018-03-18 19:29:47
【问题描述】:

目前我有以下代码

import matplotlib.pyplot as plt
import pandas as pd
from pandas.plotting import scatter_matrix

df= pd.read_csv(file, sep=',')
colors = list('r' if i==1 else 'b' for i in df['class']) # class is either 1 or 0
plt.figure()
scatter_matrix(df, color=colors )
plt.show()

它显示以下输出

但是在这个对角线上的图中,我想显示堆叠直方图,而不是简单的直方图,如下所示,对于“1”类,它是红色的,而对于“0”类,它是蓝色的

请指导我如何做到这一点?

【问题讨论】:

  • 有个包叫seaborn

标签: python pandas matplotlib histogram


【解决方案1】:

示例代码

import seaborn as sns
sns.set(style="ticks")
df = sns.load_dataset("iris")
sns.pairplot(df, hue="species")

【讨论】:

  • 还有 seaborn 和 bokeh 也可以做到这一点,但我想以某种方式使用 matplotlib。在 matplotlib 中可以吗?还是谢谢
  • 不幸的是,这个答案没有绘制 stacked 直方图。如果有人有一个很好的解决方案,可以在 seaborn 对网格中绘制堆叠直方图,我会很高兴看到它。
【解决方案2】:

使用 seaborn 可能对绘制散点矩阵类型的绘图非常有益。但是,我不知道如何在 seaborn 中轻松地将 堆叠 直方图绘制到 PairGrid 的对角线上。
无论如何,问题都要求使用 matplotlib,以下是使用 pandas 和 matplotlib 的解决方案。不幸的是,它需要手工做很多事情。以下是一个示例(请注意,由于问题未提供任何数据,因此仅导入 seaborn 以获取一些数据)。

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

# seaborn import just needed to get some data
import seaborn as sns
df = sns.load_dataset("iris")


n_hist = 10
category = "species"
columns = ["sepal_length","sepal_width","petal_length","petal_width"]
mi = df[columns].values.min()
ma = df[columns].values.max()
hist_bins = np.linspace(mi, ma, n_hist)


fig, axes = plt.subplots(nrows=len(columns), ncols=len(columns), 
                         sharex="col")

for i,row in enumerate(columns):
    for j,col in enumerate(columns):
        ax= axes[i,j]
        if i == j:
            # diagonal
            mi = df[col].values.min()
            ma = df[col].values.max()
            hist_bins = np.linspace(mi, ma, n_hist)
            def hist(x):
                h, e = np.histogram(x.dropna()[col], bins=hist_bins)
                return pd.Series(h, e[:-1])
            b = df[[col,category]].groupby(category).apply(hist).T
            values = np.cumsum(b.values, axis=1)
            for k in range(len(b.columns)):
                if k == 0:
                    ax.bar(b.index, values[:,k], width=np.diff(hist_bins)[0])
                else:
                    ax.bar(b.index, values[:,k], width=np.diff(hist_bins)[0],
                           bottom=values[:,k-1])
        else:
            # offdiagonal
            for (n,cat) in df.groupby(category):
                ax.scatter(cat[col],cat[row], s = 5,label=n, )
        ax.set_xlabel(col)
        ax.set_ylabel(row)
        #ax.legend()
plt.tight_layout()
plt.show()

【讨论】: