【问题标题】:Plot subplots inside subplots matplotlib在子图中绘制子图 matplotlib
【发布时间】:2022-08-16 10:09:23
【问题描述】:

背景:我想根据子图中数据框列中的模式绘制多个子图(由图例分隔),但是,我无法将每个子图分成另一组子图。

这就是我所拥有的:

import matplotlib.pyplot as plt
col_patterns = [\'pattern1\',\'pattern2\']
# define subplot grid
fig, axs = plt.subplots(nrows=len(col_patterns), ncols=1, figsize=(30, 80))
plt.subplots_adjust()
fig.suptitle(\"Title\", fontsize=18, y=0.95)
for col_pat,ax in zip(col_patterns,axs.ravel()):
    col_pat_columns = [col for col in df.columns if col_pat in col]

    df[col_pat_columns].plot(x=\'Week\',ax=ax)
    # chart formatting
    ax.set_title(col_pat.upper())
    ax.set_xlabel(\"\")

结果是这样的:

我怎样才能使这些子图中的每一个都变成另外 6 个子图,全部水平布置? (即每个图例都是它自己的子图)

谢谢!

  • 为什么不能将ncols 设置为您需要的值? (抱歉,如果我没有正确解释问题)
  • 嘿,这只会将每个子图并排放置。目标是根据图例将每个子图分成另一个子图。 eSoV 将是一个子图,eSoV_4_week_rolling_mean 将是另一个子图,等等。这些“eSoV”子图将水平显示给彼此

标签: python matplotlib


【解决方案1】:

在您的示例中,您正在定义一个 2x1 子图,并且仅循环通过创建的两个轴对象。在这两个循环中的每一个中,当您调用df[col_pat_columns].plot(x='Week',ax=ax) 时,由于col_pat_columns 是一个列表并且您将其传递给df,因此您只是从数据框中绘制了多个列。这就是为什么它是一个情节上的多个系列。

@fdireito 是正确的——您只需将 plt.subplots()ncols 参数设置为您需要的正确数字,但您需要调整循环以适应。

如果您想留在 matplotlib 中,那么这是一个基本示例。我不得不对您的数据框的结构等进行一些猜测。

# import matplotlib
import matplotlib.pyplot as plt

# create some fake data
x = [1, 2, 3, 4, 5]

df = pd.DataFrame({
    'a':[1, 1, 1, 1, 1],    # horizontal line
    'b':[3, 6, 9, 6, 3],    # pyramid
    'c':[4, 8, 12, 16, 20], # steep line
    'd':[1, 10, 3, 13, 5]   # zig-zag
})

# a list of lists, where each inner list is a set of
# columns we want in the same row of subplots
col_patterns = [['a', 'b', 'c'], ['b', 'c', 'd']]

以下是您的代码最终执行的简化示例。

fig, axes = plt.subplots(len(col_patterns), 1)

for pat, ax in zip(col_patterns, axes):
    ax.plot(x, df[pat])

2x1 subplot (what you have right now)

我使用enumerate()col_patterns 来遍历子图行,然后使用enumerate() 和给定模式中的每个列名来遍历子图列。

# the following will size your subplots according to
# - number of different column patterns you want matched (rows)
# - largest number of columns in a given column pattern (columns)
subplot_rows = len(col_patterns)
subplot_cols = max([len(x) for x in col_patterns])
fig, axes = plt.subplots(subplot_rows, subplot_cols)

for nrow, pat in enumerate(col_patterns):
    for ncol, col in enumerate(pat):
        axes[nrow][ncol].plot(x, df[col])

Correctly sized subplot

这是所有代码,为简单起见,我从上面的代码中省略了一些附加内容。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]

df = pd.DataFrame({
    'a':[1, 1, 1, 1, 1],    # horizontal line
    'b':[3, 6, 9, 6, 3],    # pyramid
    'c':[4, 8, 12, 16, 20], # steep line
    'd':[1, 10, 3, 13, 5]   # zig-zag
})

col_patterns = [['a', 'b', 'c'], ['b', 'c', 'd']]

# what you have now
fig, axes = plt.subplots(len(col_patterns), 1, figsize=(12, 8))

for pat, ax in zip(col_patterns, axes):
    ax.plot(x, df[pat])
    ax.legend(pat, loc='upper left')

# what I think you want
subplot_rows = len(col_patterns)
subplot_cols = max([len(x) for x in col_patterns])

fig, axes = plt.subplots(subplot_rows, subplot_cols, figsize=(16, 8), sharex=True, sharey=True, tight_layout=True)

for nrow, pat in enumerate(col_patterns):
    for ncol, col in enumerate(pat):
        axes[nrow][ncol].plot(x, df[col], label=col)
        axes[nrow][ncol].legend(loc='upper left')

您可以考虑的另一个选择是放弃 matplotlib 并使用 Seaborn relplots。该页面上有几个示例应该有所帮助。如果您的数据框设置正确(长或“整齐”的格式),那么要实现与上述相同的效果,您的单线将如下所示:

# import seaborn as sns

sns.relplot(data=df, kind='line', x=x_vals, y=y_vals, row=col_pattern, col=num_weeks_rolling)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 2021-11-06
    • 1970-01-01
    • 2015-09-23
    • 2019-02-05
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    相关资源
    最近更新 更多