简体   繁体   English

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

[英]How to align text left on a plotly bar chart (example image contained) [Plotly-Dash]

I need help in adding text to my graph.我需要帮助将文本添加到我的图表中。

I have tried text = 'y' and text-position = 'inside' but the text goes vertical or gets squashed for small bar charts so it can fit inside the bar.我已经尝试过 text = 'y' 和 text-position = 'inside' 但文本会垂直或被压扁以用于小条形图,因此它可以适合条形图。 I just want it to write across.我只是想让它写下来。

Here is a working example of the code that needs fixing:这是需要修复的代码的工作示例:

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()

Here's the output:这是 output:

在此处输入图像描述

Here's an example of how I want my text to look:这是我希望我的文本看起来如何的示例: 在此处输入图像描述

I need help with two things:我需要两件事的帮助:

  1. Make the text align to the left not the right of the bar.使文本与栏的左侧而不是右侧对齐。
  2. If the bar length is short I want the text to still be visible (even if the bar length is zero) and not squashed or vertically aligned.如果条形长度较短,我希望文本仍然可见(即使条形长度为零)并且不被压扁或垂直对齐。

If you can also give an explanation of how to fix y-axis being cut off in the third chart that would be amazing.如果您还可以解释如何修复第三张图表中被切断的 y 轴,那就太棒了。 For now, I have to change the labels to force it to fit which is time-consuming.现在,我必须更改标签以使其适合,这很耗时。 Is there a way of adding padding to the container or something?有没有办法向容器或其他东西添加填充?

Thanks.谢谢。

You can pass text into go.Bar() , where you can set textposition="inside" and insidetextanchor="start" , which should solve this issue.您可以将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()

This is an inelegant workaround, but after scouring the plotly python docs, I couldn't find anything that would do exactly what you were asking with the plotly attributes provided.这是一个不优雅的解决方法,但是在搜索了 plotly python 文档之后,我找不到任何可以使用提供的 plotly 属性完全满足您要求的东西。 If you need a one-time, quick fix now, try using yaxis=dict(showticklabels=False) and add your labels manually as annotations like:如果您现在需要一次性快速修复,请尝试使用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,
        ), 

The output I got looked like:我得到的输出看起来像: 带有标签注释的 Plotly 水平条

You can check the Plotly Annotations and Chart Attributes documentation to see if there is anything that better suits your needs.您可以查看 Plotly AnnotationsChart Attributes文档,看看是否有更适合您需求的内容。

Edit: I started posting this response before the code was added to the question.编辑:在将代码添加到问题之前,我开始发布此回复。 Here is an example of how the annotations could be made for the first two y labels of the first graph in the code in question:以下是如何为相关代码中第一个图形的前两个 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,
                                                                    ),

Edit 2: @ user8322222, to answer the question in your comment, you could use a list comprehension to make your annotations dictionary like so:编辑 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))]

However I don't think there will be a constant you could multiply by the length of the text in characters (like I used for x in the example) to get perfect alignment.但是我不认为会有一个常数可以乘以字符中的文本长度(就像我在示例中用于x一样)以获得完美对齐。 You could use the pixel length or other measures for the string as in this post to devise a more accurate way of determining x to get it properly aligned.您可以使用像素的长度或其他措施,以字符串作为这个帖子制定确定X,以得到它正确对齐的一个更准确的方法。 Hope that helps.希望有帮助。

You can prevent the y-axis from being cutoff in your third chart by changing the margins of the figure.您可以通过更改图形的边距来防止第三个图表中的 y 轴被截断。 Add the following code to the inside of the call to go.Layout() :将以下代码添加到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
        )

You can adjust the left margin for different y-axis labels, or you could set it to automatically scale with the length of the longest label.您可以调整不同 y 轴标签的左边距,也可以将其设置为根据最长标签的长度自动缩放。

没有 y 轴截止的第三个图

If you are using plotly.express plots, you can achieve that with:如果您使用plotly.express绘图,您可以通过以下方式实现:

fig.update_traces(insidetextanchor="start")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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