Python列表存储AxesSubPlot重复问题:多参数聚类子图绘制异常
问题原因
pandas的plot()方法默认会复用当前活跃的matplotlib Axes对象,所以你每次追加到列表里的其实是同一个Axes实例的引用。后续的绘图操作会覆盖这个实例的内容,最终列表里所有元素都显示最后一次的绘图结果。
解决方案
有两种常用的解决方式:
方式1:每次绘图时创建新的Axes实例
修改函数,在调用plot()时通过plt.subplots()生成新的Axes,然后指定给ax参数:
import matplotlib.pyplot as plt def ngram_range(ranges, DF, DF_col, number_clusters, lst): CV = CountVectorizer(ngram_range=tuple(ranges), analyzer='char') CV_values = CV.fit_transform(DF_col) clusters = MiniBatchKMeans(n_clusters=number_clusters, init_size=1024, batch_size=2048, random_state=20).fit_predict(CV_values) # 复制原始DataFrame,避免污染原始数据 temp_DF = DF.copy() temp_DF['Cluster'] = clusters new_DF = temp_DF.groupby('Cluster')['Cluster'].count() # 创建新的Axes实例 fig, ax = plt.subplots() plot = new_DF.plot(kind='bar', title='Cluster Frequency Ngram range from {} to {}'.format(ranges[0],ranges[1]), xlabel='Cluster', ylabel='Freq', ax=ax) lst.append(plot) return lst
方式2:预先创建子图网格,指定每个绘图的目标Axes
如果最终要把所有子图放在同一个画布上,更高效的方式是先创建好子图布局,然后循环时把每个plot指定到对应的ax:
import matplotlib.pyplot as plt ranges = [[2,2], [2,3], [2,4], [3,3],[3,4],[4,4]] # 创建2行3列的子图网格,设置画布大小 fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(15, 10)) # 把二维Axes数组转成一维,方便循环遍历 axes = axes.flatten() for idx, R in enumerate(ranges): CV = CountVectorizer(ngram_range=tuple(R), analyzer='char') CV_values = CV.fit_transform(df_ru['RU_desc']) clusters = MiniBatchKMeans(n_clusters=8, init_size=1024, batch_size=2048, random_state=20).fit_predict(CV_values) temp_DF = df_ru.copy() temp_DF['Cluster'] = clusters new_DF = temp_DF.groupby('Cluster')['Cluster'].count() # 指定当前子图的Axes对象 new_DF.plot(kind='bar', title='Ngram range {} to {}'.format(R[0], R[1]), xlabel='Cluster', ylabel='Freq', ax=axes[idx]) # 自动调整子图间距,避免标题、标签重叠 plt.tight_layout() plt.show()
额外注意点
ngram_range参数要求传入tuple类型,原代码中(ranges)是列表,显式转为tuple(ranges)更规范。- 不要直接修改原始DataFrame,复制临时DataFrame进行操作可以避免污染原始数据。
内容的提问来源于stack exchange,提问作者Tam
相关产品推荐
相关产品推荐

