JFreeChart给甘特图加一条当日时间线

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JFreeChart给甘特图加一条当日时间线相关的知识,希望对你有一定的参考价值。

如题,我用JFreeChart画甘特图来描述项目的进度,纵轴表示项目名称,横轴表示时间。
现在我遇到的问题是怎样在图上画一条平行于纵轴的当日的时间线?
样式最好是红色虚线,不过能给我画出那条线的方法就OK了,样式可以自己调。
请大侠不要粘整个图的代码过来,找不着哇,就把那条线的那两三行代码给我就好了~!

DateAxis x1Axis=new DateAxis();//设置x轴,也就是时间轴
x1Axis.setAutoRange(false);//设置不采用自动设置时间范围
try
x1Axis.setRange(dateFormat.parse("2007-08-20"),dateFormat.parse("2007-09-29"));//设置时间范围,注意时间的最大值要比已有的时间最大值要多一天
catch(Exception e)
e.printStackTrace();

x1Axis.setTimeline(SegmentedTimeline.newMondayThroughFridayTimeline());//设置时间线显示的规则,
x1Axis.setAutoTickUnitSelection(false);//设置不采用自动选择刻度值
x1Axis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);//设置标记的位置
x1Axis.setStandardTickUnits(DateAxis.createStandardDateTickUnits());//设置标准的时间刻度单位
x1Axis.setTickUnit(new DateTickUnit(DateTickUnit.DAY,7));//设置时间刻度的间隔,一般以周为单位
x1Axis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));//设置显示时间的格式
参考技术A 我交给你个简单方法,最好演示给你看,一看就会,他们说的太复杂QQ401624928

带有整数 xaxis 的甘特图的 Plotly Express 时间线?

【中文标题】带有整数 xaxis 的甘特图的 Plotly Express 时间线?【英文标题】:Plotly Express timeline for Gantt Chart with integer xaxis? 【发布时间】:2021-05-10 17:12:42 【问题描述】:

我正在使用 plotly express 时间线来生成甘特图,如下所示:https://medium.com/dev-genius/gantt-charts-in-python-with-plotly-e7213f932f1e

它会自动将 x 轴设置为使用日期,但我实际上只想使用整数(即 Project Kick-Off +1、Project Kick-Off +6 等)。

有没有办法让时间线图不使用 xaxis 的日期?

如果我尝试使用整数,它会将它们视为毫秒。

【问题讨论】:

我的建议对你有什么效果? 不完全。我仍然需要深入研究它,但它已接近成为我需要的解决方案。谢谢! 您是否考虑将我的建议标记为已接受的答案? 【参考方案1】:

答案:

是的,这是可能的!只需将整数作为开始和结束“日期”,计算它们之间的差异 (delta),然后对您的 fig 进行这些更改:

fig.layout.xaxis.type = 'linear'
fig.data[0].x = df.delta.tolist()

情节

详情:

实际上有一种方法可以实现这一点,尽管docs 声明:

px.timeline 函数默认设置 X 轴为 type=date,因此可以像任何时间序列图一样进行配置。

因此px.timeline() 中的所有其他功能似乎都围绕着这一事实。但是,如果您忽略这一点并使用整数作为StartFinish 的值,那么您可以调整一些属性以获得您想要的。您只需要计算每个StartStop 之间的差异。比如这样:

df = pd.DataFrame([
    dict(Task="Job A", Start=1, Finish=4),
    dict(Task="Job B", Start=2, Finish=6),
    dict(Task="Job C", Start=3, Finish=10)
])
df['delta'] = df['Finish'] - df['Start']

然后再稍微调整一下:

fig.layout.xaxis.type = 'linear'
fig.data[0].x = df.delta.tolist()

完整代码:

import plotly.express as px
import pandas as pd

df = pd.DataFrame([
    dict(Task="Job A", Start=1, Finish=4),
    dict(Task="Job B", Start=2, Finish=6),
    dict(Task="Job C", Start=3, Finish=10)
])
df['delta'] = df['Finish'] - df['Start']

fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task")
fig.update_yaxes(autorange="reversed") 

fig.layout.xaxis.type = 'linear'
fig.data[0].x = df.delta.tolist()
f = fig.full_figure_for_development(warn=False)
fig.show()

【讨论】:

【参考方案2】:

我尝试了此处列出的其他答案,但如果我指定 color,这将不起作用。如果我尝试,数据fig.data 有多个Bar 对象,我认为它不包含分配所有增量所需的数据。但是,我确实发现我可以通过猴子补丁 plotly code 不将其转换为时间对象,并且我得到了正确的结果:

import plotly.express as px
import pandas as pd

def my_process_dataframe_timeline(args):
    """
    Massage input for bar traces for px.timeline()
    """
    print("my method")
    args["is_timeline"] = True
    if args["x_start"] is None or args["x_end"] is None:
        raise ValueError("Both x_start and x_end are required")

    x_start = args["data_frame"][args["x_start"]]
    x_end = args["data_frame"][args["x_end"]]

    # note that we are not adding any columns to the data frame here, so no risk of overwrite
    args["data_frame"][args["x_end"]] = (x_end - x_start)
    args["x"] = args["x_end"]
    del args["x_end"]
    args["base"] = args["x_start"]
    del args["x_start"]
    return args
px._core.process_dataframe_timeline = my_process_dataframe_timeline

df = pd.DataFrame([
    dict(Task="Job A", Start=1, Finish=4, color="1"),
    dict(Task="Job B", Start=2, Finish=6, color="2"),
    dict(Task="Job C", Start=3, Finish=10, color="1")
])
df['delta'] = df['Finish'] - df['Start']

fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="color")
fig.update_yaxes(autorange="reversed") 

fig.layout.xaxis.type = 'linear'
fig.show()

显然不希望这样做...获得正式支持会很好。

【讨论】:

【参考方案3】:

当我们必须指定color时,我认为这比上面的解决方案要简单得多

for d in fig.data:
  filt = df['color'] == d.name
  d.x = df[filt]['Delta'].tolist()

【讨论】:

很抱歉,您没有回答问题 仅供参考,这是对 vestland 答案的附加评论,如果您自己尝试一下,您会发现它比像 amos 的答案那样覆盖 process_dataframe_timeline 函数要简单得多。 这确实是一个有用的评论,因为它大大简化了解决方案!初始解决方案中的问题在fig.data[0].x,因此这个 0 索引将仅修复第一系列柱,其余柱将不可见。这里提到的几行代码为我解决了这个问题,而无需修补情节代码。

以上是关于JFreeChart给甘特图加一条当日时间线的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 JFreeChart 甘特图中特定子任务的颜色?

支持甘特图和粒度的免费库 <= 1 小时

JFreeChart 之折线图

JFreeChart 之柱状图

JFreeChart的使用

jfreechart 在客户端