我正在尝试绘制甘特图和其他类似的调度图表。其中,x 轴是时间(连续,可以是浮点数或日期时间),y 轴是分类的,例如任务或机器。一个典型的图可能有 100 多个类别。图的主体由水平条组成,每个类别有零个或多个水平条。
我想将它们作为网络应用程序的一部分在浏览器中绘制。现实世界的示例将有更多的行,给出一个非常高的数字,无法在浏览器中完全查看。 因为绘图非常高,所以我希望能够设置高度上限(可能以像素为单位,或以行数为单位),并且能够在绘图内上下滚动,同时始终使轴在屏幕底部可见(不能在 HTML div 中使用大小限制和溢出,因为它会滚动到绘图之外,从而切断 x 轴)。 y 轴理想情况下不应缩放,而只能滚动。
我看过 matplotlib (
broken_barh
)、altair (
mark_bar
)、bokeh (hbar
) 和plotly (timeline
),但找不到任何简单的方法来实现这一点;我能做的最好的事情就是做一些情节之外的事情,例如一个小部件,用于选择最上面的可见类别和要显示的最大类别行数,然后过滤发送到绘图的数据。是否有任何具有交互功能的绘图库可以处理分类数据的垂直滚动?
import dash
from dash import dcc, html
import plotly.express as px
import pandas as pd
# Sample data
df = pd.DataFrame({
'Task': ['Task1', 'Task2', 'Task3', 'Task4', 'Task5'],
'Start': ['2023-01-01', '2023-01-02', '2023-01-05', '2023-01-07', '2023-01-09'],
'Finish': ['2023-01-03', '2023-01-04', '2023-01-06', '2023-01-08', '2023-01-10'],
})
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task")
fig.update_yaxes(categoryorder="total ascending")
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(figure=fig, style={"height": "500px", "overflowY": "scroll"})
])
if __name__ == '__main__':
app.run_server(debug=True)
Bokeh还支持交互式可视化,通过Panel,您可以构建Web应用程序并控制滚动 Altair 的 mark_bar 带有交互式选择器,可实现动态过滤,您可以通过小部件或下拉菜单选择可见类别
带有过滤选择器的 Altair 提供了一种滚动有限但交互性良好的替代方案,适用于一次可见行数较少的应用程序。
import altair as alt
import pandas as pd
# Data setup
df = pd.DataFrame({
'Task': ['Task1', 'Task2', 'Task3', 'Task4', 'Task5'],
'Start': pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-05', '2023-01-07', '2023-01-09']),
'Finish': pd.to_datetime(['2023-01-03', '2023-01-04', '2023-01-06', '2023-01-08', '2023-01-10']),
})
task_selection = alt.selection_single(
fields=['Task'], bind=alt.binding_select(options=df['Task'].unique().tolist())
)
gantt = alt.Chart(df).mark_bar().encode(
x='Start',
x2='Finish',
y=alt.Y('Task:N', sort=alt.SortField(field='Task')),
color='Task'
).add_selection(task_selection).transform_filter(task_selection)
gantt.show()