简体   繁体   English

修复了 plotly.express.timeline 中的条形宽度/厚度

[英]Fixed bar width/thickness in plotly.express.timeline

I'm using Plotly Express to draw a Gantt graph.我正在使用 Plotly Express 绘制甘特图。

I don't know in advance the number of horizontal lines (the number of "tasks").我事先不知道水平线的数量(“任务”的数量)。

I would like the bars to be always the same thickness.我希望钢筋的厚度始终相同。 (I believe the attribute is width, but since the bars are horizontal, "width" might be ambiguous.) (我相信属性是宽度,但由于条是水平的,“宽度”可能不明确。)

When plotting the figure directly, it takes the whole space on the page and when resizing the page, the bars change size accordingly.直接绘制图形时,它会占用页面上的整个空间,并且在调整页面大小时,条形会相应地改变大小。

import datetime as dt
import plotly.express as px


data = [
    {'Task': '1-2', 'Start': '2021-09-26', 'Finish': '2021-09-27', 'Resource': 'R1'},
    {'Task': '2-1', 'Start': '2021-09-23', 'Finish': '2021-09-24', 'Resource': 'R2'},
    {'Task': '2-2', 'Start': '2021-09-26', 'Finish': '2021-09-27', 'Resource': 'R2'},
    {'Task': '3-1', 'Start': '2021-09-30', 'Finish': '2021-10-01', 'Resource': 'R3'},
    {'Task': '3-2', 'Start': '2021-11-26', 'Finish': '2021-11-27', 'Resource': 'R3'},
]

fig = px.timeline(
    data,
    x_start="Start",
    x_end="Finish",
    y="Resource",
)

fig.show()

There is a width attribute on each bar but it controls how much of the allowed space the bar uses, so it doesn't actually fix the width.每个栏上都有一个宽度属性,但它控制栏使用的允许空间的大小,因此它实际上并没有固定宽度。

A cheap trick is to set the graph height according to the number of lines but one must take into account the surroundings (legend, title, etc.) so it is not really linear.一个廉价的技巧是根据行数设置图形高度,但必须考虑周围环境(图例、标题等),因此它不是真正的线性。 And anyway, it would be at best a sorry workaround.无论如何,这充其量只是一个遗憾的解决方法。

When I integrate the graph in a page like当我将图形集成到页面中时

Python code Python 代码

return plotly.io.to_json(fig)

HTML page HTML 页

<script src="https://cdn.plot.ly/plotly-2.0.0.min.js"></script>
<script type="text/javascript">

let graph = {{ gantt_json|safe }};
Plotly.newPlot('gantt_graph', graph, {});

</script>

the graph doesn't take the whole page, but still the bar width changes when the number of bar changes.该图并没有占据整个页面,但是当条形数量变化时条形宽度仍然会发生变化。


So I can control the total graph size, and the width of each bar relative to its allowed space, but I can't seem to find a way to get a fixed width in pixels.所以我可以控制总图形大小,以及每个条形相对于其允许空间的宽度,但我似乎无法找到一种方法来获得以像素为单位的固定宽度。

(I thought this issue and closing PR would help but they didn't.) (我认为这个问题关闭 PR会有所帮助,但他们没有。)

Am I missing something?我错过了什么吗?

  • thinking laterally this can be achieved by controlling domain of yaxis横向思考这可以通过控制yaxis来实现
  • have simulated data, which will generate a random number of timelines有模拟数据,会生成随机数的时间线
  • based on number of timelines set domain min value基于时间线的数量设置最小值
import pandas as pd
import numpy as np
import plotly.express as px
T = 8
data = pd.DataFrame(
    {
        "Start": pd.date_range("1-jan-2021", freq="2D", periods=T),
        "Finish": pd.date_range("14-jan-2021", freq="2D", periods=T),
        "Resource": np.random.choice(
            [chr(i) for i in range(ord("A"), ord("A") + T)], T
        ),
    }
)
color_map = {chr(ord("A") + i): px.colors.qualitative.Alphabet[i%len(px.colors.qualitative.Alphabet)] for i in range(T)}
fig = px.timeline(
    data,
    x_start="Start",
    x_end="Finish",
    y="Resource",
    color="Resource",
    color_discrete_map=color_map,
    #    height=10 * len(data)  # This sucks
)
fig.update_xaxes(
    side="top",
    dtick="D1",
    tickformat="%e\n%b\n%Y",
    ticklabelmode="period",
    tickangle=0,
    fixedrange=True,
)
fig.update_yaxes(
    title="",
    tickson="boundaries",
    fixedrange=True,
)
BARHEIGHT = .1
fig.update_layout(
    yaxis={"domain": [max(1 - (BARHEIGHT * len(fig.data)), 0), 1]}, margin={"t": 0, "b": 0}
)

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

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