简体   繁体   English

python plotly - 旋转辅助 X 轴标签

[英]python plotly - rotating secondary X axis labels

Let's say I create a plotly figure like this:假设我创建了一个 plotly 图形,如下所示:

x = [['A','A','B','B'], ['X','Y','X','Y']]
y = [1,2,3,2]
fig = go.Figure()
fig.add_bar(x=x, y=y)
fig.show()

I get this:我明白了: 在此处输入图像描述 I want to rotate the secondary X labels ('A' and 'B').我想旋转辅助 X 标签(“A”和“B”)。 I tried:我试过了:

fig.update_xaxes(tickangle=45)

but this only rotates the 'X' and 'Y' labels.但这只会旋转“X”和“Y”标签。 How can I do it?我该怎么做?

Based on this discussion by the plotly team, it doesn't appear that the capability to rotate both labels for a multicategorical axis was implemented, because it would be difficult to control overlapping labels if the secondary label was long.根据 plotly 团队的讨论,似乎没有实现为多类别轴旋转两个标签的功能,因为如果辅助 label 很长,则很难控制重叠标签。

In your case, the best you could probably do is add the secondary labels as annotations.在您的情况下,您可能做的最好的事情是将辅助标签添加为注释。 I replaced the each unique label with different numbers of spaces so they don't show up, but are still interpreted as another category by Plotly (eg 'A' is replaced by ' ' , 'B' is replaced by ' ' , and so on...).我用不同数量的空格替换了每个唯一的 label,因此它们不会显示,但仍被 Plotly 解释为另一个类别(例如'A'替换为' ''B'替换为' ' ,等等上...)。

Then instead of just placing down the labels where we know they should go, it's better to make a scalable function that determines where the secondary labels should be placed based on the number of secondary x-labels you have.然后,与其仅仅将标签放置在我们知道它们应该放置的位置 go 中,不如制作一个可扩展的 function,它根据您拥有的辅助 x 标签的数量确定辅助标签的放置位置。 I wrote a function that does that below (and to demonstrate, I modified the number of secondary labels):我写了一个 function 在下面(为了演示,我修改了辅助标签的数量):

import plotly.graph_objects as go

## use placeholders so labels don't show up
## map each unique label to a different number of spaces
## extend the labels to show that the solution can be generalized
secondary_labels = ['A','A','A','B','B','C']

label_set = sorted(set(secondary_labels), key=secondary_labels.index)
label_mapping = {label:' '*i for i, label in enumerate(label_set)}
secondary_labels_mapped = [label_mapping[label] for label in secondary_labels]

x = [secondary_labels_mapped, ['X','Y','Z','X','Y','X']]
y = [1,2,3,4,2,4]

## source: https://www.geeksforgeeks.org/python-program-to-find-cumulative-sum-of-a-list/
def cumsum(lists):
    cu_list = []
    length = len(lists)
    cu_list = [sum(lists[0:x:1]) for x in range(0, length+1)]
    return cu_list[1:]

relative_lengths = {}
start_loc = []
for label in label_set:
    relative_lengths[label] = secondary_labels.count(label) / len(secondary_labels)

## get the length of each interval
end_lens = list(relative_lengths.values())
start_lens = [0] + end_lens[:-1]

end_locs = cumsum(end_lens)
start_locs = cumsum(start_lens)

annotation_locs = [(start + end) / 2 for start, end in zip(start_locs, end_locs)]

fig = go.Figure()
fig.add_bar(x=x, y=y)

for label, loc in zip(label_set,annotation_locs):
    fig.add_annotation(
        x=loc,
        y=0,
        xref="paper",
        yref="paper",
        text=label,
        showarrow=False,
    )

## shift annotations down so they display on the axes
fig.update_annotations(yshift=-40)
fig.show()

在此处输入图像描述

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

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