繁体   English   中英

Plot 子图内子图 matplotlib

[英]Plot subplots inside subplots matplotlib

背景:我想 plot 多个子图(由图例分隔)基于子图中 dataframe 列中的模式但是,我无法将每个子图分成另一组子图。

这就是我所拥有的:

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 个子图,全部水平布置? (即每个图例都是它自己的子图)

谢谢!

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

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

如果你想留在matplotlib,那么这里有一个基本的例子。 我不得不猜测您的 dataframe 的结构等等。

# 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 子图(您现在拥有的)

我使用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])

正确大小的子图

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

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 该页面上有几个示例应该有所帮助。 如果您的 dataframe 设置正确(长或“整齐”的格式),那么要实现与上述相同的效果,您的单线将如下所示:

# import seaborn as sns

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM