python - 修复了 plotly.express.timeline 中的条形宽度/厚度
问题描述
我正在使用 Plotly Express 绘制甘特图。
我事先不知道水平线的数量(“任务”的数量)。
我希望这些条始终具有相同的厚度。(我相信属性是宽度,但由于条是水平的,“宽度”可能不明确。)
直接绘制图形时,它会占用页面上的整个空间,并且在调整页面大小时,条形会相应地改变大小。
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()
每个条上都有一个宽度属性,但它控制条使用的允许空间量,因此它实际上并没有固定宽度。
一个便宜的技巧是根据行数设置图形高度,但必须考虑周围环境(图例、标题等),因此它不是真正的线性。无论如何,这充其量只是一个抱歉的解决方法。
当我将图表集成到页面中时
Python代码
return plotly.io.to_json(fig)
网页
<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>
该图不会占用整个页面,但当条数发生变化时,条形宽度仍然会发生变化。
所以我可以控制图形的总大小,以及每个条相对于其允许空间的宽度,但我似乎无法找到一种方法来获得以像素为单位的固定宽度。
我错过了什么吗?
解决方案
- 横向思考这可以通过控制yaxis的域来实现
- 有模拟数据,这将生成随机数量的时间线
- 基于时间线数量设置域最小值
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}
)
推荐阅读
- swift - 无法使用 mongodb 同步打开 Realm
- python - 如何正确构造具有单个退出的递归函数?
- java - 无法创建 Java 虚拟机错误
- python - 使用 for 语句从数据框中附加列表
- python - TemplateDoesNotExist(', '.join(template_name_list), chain=chain) django.template.exceptions.TemplateDoesNotExist: home.html
- git - 如何在 Github 中创建“核心”存储库?我需要建立依赖关系
- php - 未捕获的错误:在 null 上调用成员函数 is_empty() - 添加到购物车文本更改 - wordpress/woocommerce
- python-3.x - 将值附加到特定的 DataFrame 单元格
- netsuite - 在表单上有一个我无法摆脱的字段
- javascript - 正则表达式:匹配嵌套括号