Python 2.7 对齐matplotlib中各个点的标记并删除;“双”字;Python中matplotlib中标记的图例

Python 2.7 对齐matplotlib中各个点的标记并删除;“双”字;Python中matplotlib中标记的图例,python-2.7,matplotlib,markers,Python 2.7,Matplotlib,Markers,我试图找出“斧头图”中标记的对齐方式。除了绘制2个条形图外,我还需要绘制2个点,每个条形图一个点。 这就是我要找的-: 标记的居中/对齐(“o”和“”位于每个条形图的中心,而不是条形图的边缘。“o”应位于第一个条形图的中心,“o”应位于第二个条形图的中心,但它们各自的高度会有所不同,因为在“性能”标尺上,“o”和“o”是“性能”对象(如图所示,右侧比例)-居中,因此意味着标记(“o”和“”相对于其各自的堆叠图形重叠。 删除重复的标记符号,在右上角的图例中使用“o”和“*”。并且理解为什么par2

我试图找出“斧头图”中标记的对齐方式。除了绘制2个条形图外,我还需要绘制2个点,每个条形图一个点。 这就是我要找的-:

  • 标记的居中/对齐(“o”和“”位于每个条形图的中心,而不是条形图的边缘。“o”应位于第一个条形图的中心,“o”应位于第二个条形图的中心,但它们各自的高度会有所不同,因为在“性能”标尺上,“o”和“o”是“性能”对象(如图所示,右侧比例)-居中,因此意味着标记(“o”和“”相对于其各自的堆叠图形重叠。

  • 删除重复的标记符号,在右上角的图例中使用“o”和“*”。并且理解为什么par2.plot会出现这种情况,而ax.bar对象不会。我是否可以在不使用ax.twinx()的情况下执行此操作,ax.twinx()会生成两个刻度(一个用于“#候选者”,另一个用于“性能”“-如果这个双输入图例与使用2个刻度有关?(我希望不是)

    对于(2),根据这里的答案,我还在最后一行plt,show()之前使用了
    plt.legend(numpoints=1),但这似乎并没有删除上下文中的“重复标记”

  • 同时附上图表,突出显示(1)和(2)

    提示-:忽略循环结构,它们是较大部分的一部分,不想在粘贴时更改,请关注整个代码的这一片段(依我看,这应该可以缩小问题?)

    以下是我使用的完整代码-:

    #Final plotting file 
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib import rc
    #placing anchored text within the figure
    from mpl_toolkits.axes_grid.anchored_artists import AnchoredText
    rc('mathtext', default='regular')
    
    history_P=[[1.4155322812819471, 4.9723842851306213, 3.6831354714462456, 3.0345047089322521, 5.3355879766963819], [2.3240101637275856, 4.7804345245879354, 7.0829471987293973, 6.1050663075245852, 3.6087166298399973], [3.5770722538162265, 3.4516290562530587, 4.4851829512197678, 5.1158026103364733, 3.7873662329909235], [4.7137003352158136, 5.0792119756378593, 4.4624078437179504, 3.1790266221827754, 4.8711126648436895], [4.8043291762010414, 5.6979872315568576, 3.4869780377350339, 3.892755123606721, 3.8142509389863095], [4.8072846135271492, 4.2055137431209033, 5.0441056822018417, 4.1014759291893306, 5.327936039526822]]
    history_C=[[14000, 14000, 14000, 14000, 14000], [5373, 18874, 13981, 11519, 20253], [6806, 14001, 20744, 17880, 10569], [12264, 11834, 15377, 17540, 12985], [14793, 15940, 14004, 9977, 15286], [15500, 18384, 11250, 12559, 12307]]
    
    N = 5
    ind = np.arange(N)  # the x locations for the groups
    width = 0.35
    
    def make_patch_spines_invisible(ax):
        ax.set_frame_on(True)
        ax.patch.set_visible(False)
        for sp in ax.spines.itervalues():
            sp.set_visible(False)
    
    def autolabel(rects):
        # attach some text labels
        for rect in rects:
            height = rect.get_height()
            ax.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%d'%int(height),ha='center', va='bottom')
    
    alphab = ['M1', 'M2', 'M3', 'M4', 'M5', 'M6']
    
    for k in range(0,5):
        colors=[]
        Current_Period=history_C[k]
        Next_Period = history_C[k+1]
        perform_1=history_P[k]
        perform_2=history_P[k+1]
    
        for i in range(0,5):
            if perform_1[i]==max(perform_1) :
                colors.append('g')
                best=i
            elif perform_1[i]==min(perform_1):
                colors.append('r')
                worst=i
            elif (perform_1[i] != min(perform_1) or perform_1[i] != max(perform_1)):
                colors.append('b')
    
        fig, ax = plt.subplots()
        fig.subplots_adjust(right=0.75)
    
        par1 = ax.twinx()
        make_patch_spines_invisible(par1)
    
        rects1 = ax.bar(ind, Current_Period, width, color=colors)
        rects2 = ax.bar(ind+width, Next_Period, width, color='c')
        lines_1=par1.plot(perform_1,linestyle='', marker='H', markerfacecolor ='k')
        lines_2=par1.plot(perform_2,linestyle='', marker='*',markerfacecolor ='m')
        ax.set_xlabel("Model #",style='italic',size='large')
        ax.set_ylabel("Candidate #",style='italic',size='large')
        par1.set_ylabel("Performance",style='italic',size='large')
    
    
        ax.set_title('Aggregated Performace Rolled out to candidates, per period',style='italic')
        #fontdict=dict('fontsize':rcParams['axes.titlesize'],'verticalalignment': 'baseline', 'horizontalalignment': loc)
        ax.set_xticks(ind+width)
        ax.set_xticklabels( ('M1', 'M2', 'M3', 'M4', 'M5') )
        ax.annotate('Worst Performer', xy=(worst,0),  xycoords='data',xytext=(-30, 30), textcoords='offset points',size=12, va="center", ha="center",arrowprops=dict(arrowstyle="simple", connectionstyle="arc3,rad=-0.2"))
        ax.annotate('Best Performer', xy=(best,0),  xycoords='data',xytext=(-30, 30), textcoords='offset points',size=12, va="center", ha="center",arrowprops=dict(arrowstyle="simple", connectionstyle="arc3,rad=-0.2"))
        ax.legend((rects1[0], rects2[0],lines_1[0],lines_2[0]), ('Current time period', 'Next time Period','Current Period Performance', 'Next Period Performance'),prop=dict(size=10) )
        #placing anchored text within the figure, per Period
        at = AnchoredText("Time Period :"+str(k+1),prop=dict(size=10), frameon=True,loc=2,)
        at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
        ax.add_artist(at)
        par1.set_ylim(0, 10)
    
        autolabel(rects1)
        autolabel(rects2)
        plt.show()
    
  • 必须为该方法提供x坐标参数。如果只提供一个类似列表的对象,matplotlib将使用该列表作为y坐标,并使用
    x=np.arange(len(y))
    (其中
    y
    是给定的y坐标)

  • 对于每个
    ,不应多次调用该方法;在原始的
    图例
    调用中包括
    numpoints
    kwarg

  • 换言之,替换这些行

    lines_1=par1.plot(perform_1,linestyle='', marker='H', markerfacecolor ='k')
    lines_2=par1.plot(perform_2,linestyle='', marker='*',markerfacecolor ='m')
    ax.legend((rects1[0], rects2[0],lines_1[0],lines_2[0]), ('Current time period', 'Next time Period','Current Period Performance', 'Next Period Performance'),prop=dict(size=10) )
    

    这就产生了期望输出:


    我认为使用
    条(…,align='center')
    稍微好一点,因为这正是您真正想要的:

        rects1 = ax.bar(ind, Current_Period, width, color=colors, align='center')
        rects2 = ax.bar(ind+width, Next_Period, width, color='c', align='center')
        lines_1=par1.plot(ind, perform_1,linestyle='', marker='H', markerfacecolor ='k')
        lines_2=par1.plot(ind+width, perform_2,linestyle='', marker='*',markerfacecolor ='m')
        ax.set_xticks(ind + width/2)
        ax.set_xticklabels( ('M1', 'M2', 'M3', 'M4', 'M5') )
        ax.legend((rects1[0], rects2[0],lines_1[0],lines_2[0]), ('Current time period', 'Next time Period','Current Period Performance', 'Next Period Performance'),prop=dict(size=10), numpoints=1 )
    

    从哲学的角度来看,告诉绘图库做你想做的事情比扭曲你自己(并在绘图库内部注入细节)要好为了适应您只使用部分api的事实。

    一般来说,每个问题只需问一个问题。与此同时,我还发现,如果您使用散点图,解决图例中三个点的最简单方法是使用“散点=1”,而不是条形图,即plt.legend((rects[0],rects[0])),(“当前时间段”,“下一个时间段”),prop=dict(大小=10),numpoints=1,scatterpoints=1)感谢@nordev-这是我一直在寻找的最快的解决方法。+1没有引入额外的修饰结构,并且无缝地适合我的实际代码/解决方案。@ekta
    center
    不是一个“修饰结构”,它是API的一部分。您必须使用
    ax.plot指定第二个
    绘图的x坐标(ind+width,执行_2,…
    ,以便将其置于第二个条的中心。
    lines_1=par1.plot(ind + 0.5*width, perform_1,linestyle='', marker='H', markerfacecolor ='k')
    lines_2=par1.plot(ind + 1.5*width, perform_2,linestyle='', marker='*',markerfacecolor ='m')
    ax.legend((rects1[0], rects2[0],lines_1[0],lines_2[0]), ('Current time period', 'Next time Period','Current Period Performance', 'Next Period Performance'),prop=dict(size=10), numpoints=1 )
    
        rects1 = ax.bar(ind, Current_Period, width, color=colors, align='center')
        rects2 = ax.bar(ind+width, Next_Period, width, color='c', align='center')
        lines_1=par1.plot(ind, perform_1,linestyle='', marker='H', markerfacecolor ='k')
        lines_2=par1.plot(ind+width, perform_2,linestyle='', marker='*',markerfacecolor ='m')
        ax.set_xticks(ind + width/2)
        ax.set_xticklabels( ('M1', 'M2', 'M3', 'M4', 'M5') )
        ax.legend((rects1[0], rects2[0],lines_1[0],lines_2[0]), ('Current time period', 'Next time Period','Current Period Performance', 'Next Period Performance'),prop=dict(size=10), numpoints=1 )