如何在绘图条形图上左对齐文本(包含示例图像)[Plotly-Dash]

Posted

技术标签:

【中文标题】如何在绘图条形图上左对齐文本(包含示例图像)[Plotly-Dash]【英文标题】:How to align text left on a plotly bar chart (example image contained) [Plotly-Dash] 【发布时间】:2019-08-19 03:14:27 【问题描述】:

我在向图表添加文本时需要帮助。

我已经尝试过 text = 'y' 和 text-position = 'inside',但文本变为垂直或被压扁以适合小条形图,因此它可以放在条形图内。我只是想让它写出来。

这是需要修复的代码的工作示例:

app = dash.Dash(__name__)
app.css.append_css('external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css')

    labels1 = ['0-7', '8-12', '13-15', '16-20', '21-25', '26+']
values1 = [10, 30, 10, 5, 6, 8]


labels2 = ['India', 'Scotland', 'Germany', 'NW England', 'N Ireland', 'Norway', 'NE England', 'Paris', 'North Africa', 'scandinavia']
values2 = [1, 0, 4, 9, 11, 18, 50, 7, 0, 2]

values3 = [10, 111, 75, 20]
labels4 = ['Safety Manager', 'Office Administrator', 'Internal Officer', 'Assistant Producer']

bar_color = ['#f6fbfc', '#eef7fa', '#e6f3f7', '#deeff5', '#d6ebf2', '#cde7f0', '#c5e3ed', '#bddfeb', '#b5dbe8', '#add8e6']
bar_color2 = ['#e6f3f7', '#deeff5', '#d6ebf2', '#cde7f0', '#c5e3ed', '#bddfeb', '#b5dbe8', '#add8e6']

app.layout = html.Div([
  html.Div([ 
    html.Div([
        dcc.Graph(id = 'age',
                          figure = 
                                    'data': [go.Bar(x = values1,
                                                    y = labels1,
                                                    orientation = 'h',
                                                    marker=dict(color = bar_color2),
                                                    text = labels1,
                                                    textposition = 'inside'
                                                    )
                                            ],
                                    'layout': go.Layout(title = 'Number of respondees per tenure',
                                                        yaxis=dict(
                                                                   zeroline=False,
                                                                   showline=False,
                                                                   showgrid = False,
                                                                   autorange="reversed",
                                                                   ),
                                                            xaxis=dict(
                                                                      zeroline=False,
                                                                      showline=False,
                                                                      showgrid = False
                                                                      )
                                                       )
                                  
                         )
    ], className = 'four columns'),


    html.Div([
       dcc.Graph(id = 'location',
                                 figure = 
                                          'data': [go.Bar(x = values2,
                                                          y = labels2,
                                                          orientation = 'h',
                                                          marker=dict(color = bar_color),
                                                            text = labels2,
                                                            textposition = 'inside'
                                                         )
                                                  ],
                                          'layout': go.Layout(title = 'Number of respondees per region',
                                                                yaxis=dict(
                                                                          zeroline=False,
                                                                          showline=False,
                                                                          showgrid = False,
                                                                          autorange="reversed",
                                                                         ),
                                                                xaxis=dict(
                                                                          zeroline=False,
                                                                          showline=False,
                                                                          showgrid = False
                                                                         )                                                             ) 
                                        
                                )
        ], className = 'four columns'),

    html.Div([
            dcc.Graph(id = 'job',
                                  figure = 
                                            'data': [go.Bar(x = values3,
                                                            y = labels4,
                                                            orientation = 'h',
                                                            marker=dict(color = bar_color2),
                                                            text = labels4,
                                                            textposition = 'inside'                                                            
                                                           )
                                                    ],
                                           'layout': go.Layout(title = 'Number of respondees per role',
                                                               yaxis=dict(
#                                                                         automargin=True,
                                                                          zeroline=False,
                                                                          showline=False,
                                                                          showgrid = False,
                                                                          autorange="reversed",
                                                                         ),
                                                                xaxis=dict(
                                                                          zeroline=False,
                                                                          showline=False,
                                                                          showgrid = False
                                                                         )
                                                              ) 
                                           
                                )
        ], className = 'four columns')


  ], className = 'row')

])

if __name__ == '__main__':
app.run_server()

这是输出:

以下是我希望文本外观的示例:

我在两件事上需要帮助:

    使文本左对齐而不是右对齐。 如果条形长度很短,我希望文本仍然可见(即使条形长度为零)并且不会被压扁或垂直对齐。

如果您还可以在第三张图表中解释如何修复 y 轴被切断,那就太棒了。现在,我必须更改标签以强制其适合,这很耗时。有没有办法为容器添加填充或其他东西?

谢谢。

【问题讨论】:

您能提供绘制有问题的条形图的最少代码吗? @InonPeled 完成。干杯。 变量“html”是如何定义的? 【参考方案1】:

您可以将text 传递给go.Bar(),在这里您可以设置textposition="inside"insidetextanchor="start",应该可以解决这个问题。

fig = go.Figure(go.Bar(
            x=[20, 14, 23],
            y=['giraffes', 'orangutans', 'monkeys'],
            orientation='h',
            # define the annotations
            text=['giraffes', 'orangutans', 'monkeys'],
            # position, "auto", "inside" or "outside"
            textposition="auto",
            # anchor could be "start" or "end"
            insidetextanchor="start",
            insidetextfont=dict(family='Times', size=13, color='white'),
            outsidetextfont=dict(family='Times', size=13, color='white')))
fig.update_layout(
    yaxis=dict(
        showticklabels=False,
    ))
fig.show()

【讨论】:

感谢您的回答,非常有帮助!只是想补充一点,你也可以使用锚点“中间”:The 'insidetextanchor' property is an enumeration that may be specified as one of the following enumeration values: ['end', 'middle', 'start']【参考方案2】:

您可以通过更改图形的边距来防止 y 轴在第三个图表中被截断。在对go.Layout()的调用内部添加以下代码:

margin=go.layout.Margin(
        l=150, # left margin, in px
        r=80, # right margin, in px
        t=80, # top margin, in px
        b=80, # bottom margin, in px
        pad=0
        )

您可以调整不同 y 轴标签的左边距,也可以将其设置为根据最长标签的长度自动缩放。

【讨论】:

【参考方案3】:

这是一个不优雅的解决方法,但是在搜索了 plotly python 文档之后,我找不到任何可以完全按照您所要求的提供的 plotly 属性。如果您现在需要一次性快速修复,请尝试使用 yaxis=dict(showticklabels=False) 并手动添加标签作为注释,例如:

layout = go.Layout(
    # Hide the y tick labels
        yaxis=dict(
        showticklabels=False),
    annotations=[
        dict(
        # I had to try different x values to get alignment
            x=0.8,
            y='giraffes',
            xref='x',
            yref='y',
            text='Giraffes',
            font=dict(
                family='Arial',
                size=24,
                color='rgba(255, 255, 255)'
            ),
            align='left',
        # Don't show any arrow
            showarrow=False,
        ), 

我得到的输出看起来像:

您可以查看 Plotly Annotations 和 Chart Attributes 文档,看看是否有更适合您需求的内容。

编辑:我在将代码添加到问题之前就开始发布此回复。以下是如何为相关代码中第一个图形的前两个 y 标签制作注释的示例:

app.layout = html.Div([
  html.Div([ 
    html.Div([
        dcc.Graph(id = 'age',
                          figure = 
                                    'data': [go.Bar(x = values1,
                                                    y = labels1,
                                                    orientation = 'h',
                                                    marker=dict(color = bar_color2),
                                                    text = labels1,
                                                    textposition = 'inside'
                                                    )
                                            ],
                                    'layout': go.Layout(title = 'Number of respondees per tenure',
                                                        yaxis=dict(
                                                                   zeroline=False,
                                                                   showline=False,
                                                                   showgrid = False,
                                                                   showticklabels=False
                                                                   autorange="reversed",
                                                                   ),
                                                            xaxis=dict(
                                                                      zeroline=False,
                                                                      showline=False,
                                                                      showgrid = False
                                                                      )
                                                                   ),
                                                            annotations=[dict(
                                                                        x=0.8,
                                                                        y=labels1[0],
                                                                        xref='x',
                                                                        yref='y',
                                                                        text=labels1[0],
                                                                        font=dict(
                                                                            family='Arial',
                                                                            size=24,
                                                                            color='rgba(255, 255, 255)'
                                                                        ),
                                                                        align='left',
                                                                        showarrow=False,
                                                                    ), 
                                                                    dict(
                                                                        x=1.2,
                                                                        y=labels1[1],
                                                                        xref='x',
                                                                        yref='y',
                                                                        text=labels1[1],
                                                                        font=dict(
                                                                            family='Arial',
                                                                            size=24,
                                                                            color='rgba(255, 255, 255)'
                                                                        ),
                                                                        align='left',
                                                                        showarrow=False,
                                                                    ),

编辑 2: @ user8322222,要回答您评论中的问题,您可以使用列表理解来制作您的注释字典,如下所示:

 annotations1 = [dict(x=(len(labels1[i])*0.15), y=labels1[i], xref='x', yref='y', 
text=labels1[i], font=dict(family='Arial', size=24, color='rgba(255, 255, 255)'),
      align='left', showarrow=False) for i in range(len(labels1))]

但是我不认为会有一个常数,你可以乘以字符中的文本长度(就像我在示例中使用的 x 一样)以获得完美的对齐。您可以使用this post 中字符串的像素长度或其他度量来设计一种更准确的方法来确定 x 以使其正确对齐。希望对您有所帮助。

【讨论】:

哇,这很有趣,谢谢。您是否知道一种更快的方法来循环遍历标签以进行注释? 谢谢,我使用 x=0 和 xref='paper' 来垂直对齐所有文本。这些条形图连接到包含某些主题的下拉列表。例如,如果我选择一个没有印度的主题,印度的注释仍会出现在页面上,但图表不会。注释出现在其他条的间隙之间。您是否知道解决此问题的方法?

以上是关于如何在绘图条形图上左对齐文本(包含示例图像)[Plotly-Dash]的主要内容,如果未能解决你的问题,请参考以下文章

如何在绘图快速条形图中添加一条线

如何在条形图上更正 R 中 y 轴的比例和顺序

Plotly:如何对条形图上显示的“文本”值求和?

Plotly 条形图上的错误栏阻止的文本

如何在条形图上显示数值计数

如何对齐图像中心的文本