matplotlib如何仅为单个图表设置全局属性且不影响其他绘图?
方案1:使用rc_context临时上下文管理器(最推荐)
matplotlib自带的rc_context专门用于临时覆盖rc参数,退出上下文范围后会自动恢复到修改前的原有配置,不需要手动记录旧值,也不会重置为系统默认值。
你可以直接把函数里绘图相关的逻辑都包在rc_context里,示例修改后的代码如下:
import matplotlib.pyplot as plt def catscatter(data,colx,coly,cols,color=['grey','black'],ratio=10,font='Helvetica',save=False,save_name='Default'): ''' 该函数用于为分类变量创建散点图,适用于比较两个存在共同元素的列表。 ''' df = data.copy() # 创建字典将分类变量编码为数值(已排序) colx_codes=dict(zip(df[colx].sort_values().unique(),range(len(df[colx].unique())))) coly_codes=dict(zip(df[coly].sort_values(ascending=False).unique(),range(len(df[coly].unique())))) # 应用编码 df[colx]=df[colx].apply(lambda x: colx_codes[x]) df[coly]=df[coly].apply(lambda x: coly_codes[x]) # --------------- 临时修改rc参数的核心部分 --------------- # 把你需要改的rc参数以字典形式传入rc_context custom_rc = { 'xtick.bottom': False, 'xtick.labelbottom': False, 'xtick.top': True, 'xtick.labeltop': True, 'font.sans-serif': font, 'xtick.color': color[-1], 'ytick.color': color[-1] } with plt.rc_context(custom_rc): plt.box(False) # 绘制所有背景线 for num in range(len(coly_codes)): plt.hlines(num,-1,len(colx_codes),linestyle='dashed',linewidth=2,color=color[num%2],alpha=0.5) for num in range(len(colx_codes)): plt.vlines(num,-1,len(coly_codes),linestyle='dashed',linewidth=2,color=color[num%2],alpha=0.5) # 绘制数值散点图 plt.scatter(df[colx], df[coly], s=df[cols]*ratio, zorder=2, color=color[-1]) # 将刻度数值替换为分类标签并设置范围 plt.xticks(ticks=list(colx_codes.values()),labels=colx_codes.keys(),rotation=90) plt.yticks(ticks=list(coly_codes.values()),labels=coly_codes.keys()) # 按需保存图片 if save: plt.savefig(save_name+'.png') # 出了with块之后rc参数自动恢复为调用函数前的状态
方案2:手动备份原有参数后恢复
如果你不想用上下文管理器,也可以在修改rc参数前先把要改的参数原值存下来,函数执行完成最后再把值改回去:
def catscatter(data,colx,coly,cols,color=['grey','black'],ratio=10,font='Helvetica',save=False,save_name='Default'): ''' 该函数用于为分类变量创建散点图,适用于比较两个存在共同元素的列表。 ''' # --------------- 先备份要修改的参数原值 --------------- old_rc = { 'xtick.bottom': plt.rcParams['xtick.bottom'], 'xtick.labelbottom': plt.rcParams['xtick.labelbottom'], 'xtick.top': plt.rcParams['xtick.top'], 'xtick.labeltop': plt.rcParams['xtick.labeltop'], 'font.sans-serif': plt.rcParams['font.sans-serif'], 'xtick.color': plt.rcParams['xtick.color'], 'ytick.color': plt.rcParams['ytick.color'] } try: # 原有函数逻辑,修改rc参数、绘图的代码都放这里 df = data.copy() # 创建字典将分类变量编码为数值(已排序) colx_codes=dict(zip(df[colx].sort_values().unique(),range(len(df[colx].unique())))) coly_codes=dict(zip(df[coly].sort_values(ascending=False).unique(),range(len(df[coly].unique())))) # 应用编码 df[colx]=df[colx].apply(lambda x: colx_codes[x]) df[coly]=df[coly].apply(lambda x: coly_codes[x]) # 配置绘图外观 plt.rcParams['xtick.bottom'] = plt.rcParams['xtick.labelbottom'] = False plt.rcParams['xtick.top'] = plt.rcParams['xtick.labeltop'] = True plt.rcParams['font.sans-serif']=font plt.rcParams['xtick.color']=color[-1] plt.rcParams['ytick.color']=color[-1] plt.box(False) # 剩下的绘图、保存逻辑和原来一致 # 绘制所有背景线 for num in range(len(coly_codes)): plt.hlines(num,-1,len(colx_codes),linestyle='dashed',linewidth=2,color=color[num%2],alpha=0.5) for num in range(len(colx_codes)): plt.vlines(num,-1,len(coly_codes),linestyle='dashed',linewidth=2,color=color[num%2],alpha=0.5) # 绘制数值散点图 plt.scatter(df[colx], df[coly], s=df[cols]*ratio, zorder=2, color=color[-1]) # 将刻度数值替换为分类标签并设置范围 plt.xticks(ticks=list(colx_codes.values()),labels=colx_codes.keys(),rotation=90) plt.yticks(ticks=list(coly_codes.values()),labels=coly_codes.keys()) # 按需保存图片 if save: plt.savefig(save_name+'.png') finally: # 不管函数执行是否报错,最终都把rc参数恢复为原值 for k, v in old_rc.items(): plt.rcParams[k] = v
额外优化建议
如果不想碰全局rc参数,也可以直接针对当前绘图的Axes对象设置属性,完全不影响全局配置,比如把刻度相关的设置改成针对ax的操作:
ax = plt.gca() ax.tick_params(axis='x', bottom=False, labelbottom=False, top=True, labeltop=True, color=color[-1]) ax.tick_params(axis='y', color=color[-1]) ax.set_facecolor('none') # 字体设置可以在设置刻度、标题的时候单独指定,也不会影响全局
内容的提问来源于stack exchange,提问作者Ailurophile
相关产品推荐
相关产品推荐

