简体   繁体   中英

python - matplot lib sub-plot grid: where to insert row/column arguments

I'm trying to display the topic extraction results of an LDA text analysis across several data sets in the form of a matplotlib subplot.

Here's where I'm at:

I think my issue is my unfamiliarity with matplotlib. I have done all my number crunching ahead of time so that I can focus on how to plot the data:

top_words_master = []
top_weights_master = []
for i in range(len(tf_list)):
    tf = tf_vectorizer.fit_transform(tf_list[i])
    lda.fit(tf)
    n_top_words = 20
    tf_feature_names = tf_vectorizer.get_feature_names_out()
    top_features_ind = lda.components_[0].argsort()[: -n_top_words - 1 : -1]
    top_features = [tf_feature_names[i] for i in top_features_ind]
    weights = lda.components_[0][top_features_ind]
    top_words_master.append(top_features)
    top_weights_master.append(weights)

This gives me my words and my weights (the x axis values) to make my sub-plot matrix of row/bar charts.

My attempt to construct this via matplot lib:

fig, axes = plt.subplots(2, 5, figsize=(30, 15), sharex=True)
plt.subplots_adjust(hspace=0.5)
fig.suptitle("Topics in LDA Model", fontsize=18, y=0.95)
axes = axes.flatten()
for i in range(len(tf_list)):

    ax = axes[i]
    ax.barh(top_words_master[i], top_weights_master[i], height=0.7)
    ax.set_title(topic_map[f"Topic {i +1}"], fontdict={"fontsize": 30})
    ax.invert_yaxis()
    ax.tick_params(axis="both", which="major", labelsize=20)
    for j in "top right left".split():
        ax.spines[j].set_visible(False)
    fig.suptitle("Topics in LDA Model", fontsize=40)

    plt.subplots_adjust(top=0.90, bottom=0.05, wspace=0.90, hspace=0.3)
    plt.show()

However, it only showed one, the first one. For the remaining 6 data sets it just printed:

<Figure size 432x288 with 0 Axes> <Figure size 432x288 with 0 Axes> <Figure size 432x288 with 0 Axes> <Figure size 432x288 with 0 Axes> <Figure size 432x288 with 0 Axes>

Question

I've been at this for days. I feel I'm close, but this kind of result is really puzzling me, anyone have a solution or able to point me in the right direction?

You should create the figure first:

def top_word_comparison(axes, model, feature_names, n_top_words):
    for topic_idx, topic in enumerate(model.components_):
        top_features_ind = topic.argsort()[: -n_top_words - 1 : -1]
        top_features = [feature_names[i] for i in top_features_ind]
        weights = topic[top_features_ind]

        ax = axes[topic_idx]
        ax.barh(top_features, weights, height=0.7)
        ax.set_title(topic_map[f"Topic {topic_idx +1}"], fontdict={"fontsize": 30})
        ax.invert_yaxis()
        ax.tick_params(axis="both", which="major", labelsize=20)
        for i in "top right left".split():
            ax.spines[i].set_visible(False)

tf_list = [cm_array, xb_array]
fig, axes = plt.subplots(len(tf_list), 5, figsize=(30, 15), sharex=True)
fig.suptitle("Topics in LDA model", fontsize=40)

for i in range(enumerate(tf_list)):
    tf = tf_vectorizer.fit_transform(tf_list[i])
    n_components = 1
    lda.fit(tf)
    n_top_words = 20
    tf_feature_names = tf_vectorizer.get_feature_names_out()
    top_word_comparison(axes[i], lda, tf_feature_names, n_top_words)

plt.subplots_adjust(top=0.90, bottom=0.05, wspace=0.90, hspace=0.3)
plt.show()

As far as I understood from your question, your problem is to get the right indices for your subplots.

In your case, you have an array range(len(tf_list)) to index your data, some data (eg top_words_master[i] ) to plot, and a figure with 10 subplots (rows=2,cols=5). For example, if you want to plot the 7th item (i=6) of your data, the indices of ax would be axes[1,1] .

In order to get the correct indices for the subplot axes, you can use numpy.unravel_index . And, of course, you should not flatten your axes .

import matplotlib.pyplot as plt
import numpy as np


# dummy function
my_func = lambda x: np.random.random(x)
x_max = 100

# fig properties
rows = 2
cols = 5
fig, axes = plt.subplots(rows,cols,figsize=(30, 15), sharex=True)

for i in range(rows*cols):
    ax_i = np.unravel_index(i,(rows,cols))
    
    axes[ax_i[0],ax_i[1]].barh(np.arange(x_max),my_func(x_max), height=0.7)

plt.show()

结果

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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