2022-05-23 00:16:32 +04:00

1037 lines
34 KiB
Python

from __future__ import absolute_import
from numbers import Number
import copy
from plotly import exceptions, optional_imports
import plotly.colors as clrs
from plotly.figure_factory import utils
import plotly.graph_objects as go
pd = optional_imports.get_module("pandas")
REQUIRED_GANTT_KEYS = ["Task", "Start", "Finish"]
def _get_corner_points(x0, y0, x1, y1):
"""
Returns the corner points of a scatter rectangle
:param x0: x-start
:param y0: y-lower
:param x1: x-end
:param y1: y-upper
:return: ([x], [y]), tuple of lists containing the x and y values
"""
return ([x0, x1, x1, x0], [y0, y0, y1, y1])
def validate_gantt(df):
"""
Validates the inputted dataframe or list
"""
if pd and isinstance(df, pd.core.frame.DataFrame):
# validate that df has all the required keys
for key in REQUIRED_GANTT_KEYS:
if key not in df:
raise exceptions.PlotlyError(
"The columns in your dataframe must include the "
"following keys: {0}".format(", ".join(REQUIRED_GANTT_KEYS))
)
num_of_rows = len(df.index)
chart = []
for index in range(num_of_rows):
task_dict = {}
for key in df:
task_dict[key] = df.iloc[index][key]
chart.append(task_dict)
return chart
# validate if df is a list
if not isinstance(df, list):
raise exceptions.PlotlyError(
"You must input either a dataframe " "or a list of dictionaries."
)
# validate if df is empty
if len(df) <= 0:
raise exceptions.PlotlyError(
"Your list is empty. It must contain " "at least one dictionary."
)
if not isinstance(df[0], dict):
raise exceptions.PlotlyError("Your list must only " "include dictionaries.")
return df
def gantt(
chart,
colors,
title,
bar_width,
showgrid_x,
showgrid_y,
height,
width,
tasks=None,
task_names=None,
data=None,
group_tasks=False,
show_hover_fill=True,
show_colorbar=True,
):
"""
Refer to create_gantt() for docstring
"""
if tasks is None:
tasks = []
if task_names is None:
task_names = []
if data is None:
data = []
for index in range(len(chart)):
task = dict(
x0=chart[index]["Start"],
x1=chart[index]["Finish"],
name=chart[index]["Task"],
)
if "Description" in chart[index]:
task["description"] = chart[index]["Description"]
tasks.append(task)
# create a scatter trace for every task group
scatter_data_dict = dict()
marker_data_dict = dict()
if show_hover_fill:
hoverinfo = "name"
else:
hoverinfo = "skip"
scatter_data_template = {
"x": [],
"y": [],
"mode": "none",
"fill": "toself",
"hoverinfo": hoverinfo,
}
marker_data_template = {
"x": [],
"y": [],
"mode": "markers",
"text": [],
"marker": dict(color="", size=1, opacity=0),
"name": "",
"showlegend": False,
}
# create the list of task names
for index in range(len(tasks)):
tn = tasks[index]["name"]
# Is added to task_names if group_tasks is set to False,
# or if the option is used (True) it only adds them if the
# name is not already in the list
if not group_tasks or tn not in task_names:
task_names.append(tn)
# Guarantees that for grouped tasks the tasks that are inserted first
# are shown at the top
if group_tasks:
task_names.reverse()
color_index = 0
for index in range(len(tasks)):
tn = tasks[index]["name"]
del tasks[index]["name"]
# If group_tasks is True, all tasks with the same name belong
# to the same row.
groupID = index
if group_tasks:
groupID = task_names.index(tn)
tasks[index]["y0"] = groupID - bar_width
tasks[index]["y1"] = groupID + bar_width
# check if colors need to be looped
if color_index >= len(colors):
color_index = 0
tasks[index]["fillcolor"] = colors[color_index]
color_id = tasks[index]["fillcolor"]
if color_id not in scatter_data_dict:
scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template)
scatter_data_dict[color_id]["fillcolor"] = color_id
scatter_data_dict[color_id]["name"] = str(tn)
scatter_data_dict[color_id]["legendgroup"] = color_id
# if there are already values append the gap
if len(scatter_data_dict[color_id]["x"]) > 0:
# a gap on the scatterplot separates the rectangles from each other
scatter_data_dict[color_id]["x"].append(
scatter_data_dict[color_id]["x"][-1]
)
scatter_data_dict[color_id]["y"].append(None)
xs, ys = _get_corner_points(
tasks[index]["x0"],
tasks[index]["y0"],
tasks[index]["x1"],
tasks[index]["y1"],
)
scatter_data_dict[color_id]["x"] += xs
scatter_data_dict[color_id]["y"] += ys
# append dummy markers for showing start and end of interval
if color_id not in marker_data_dict:
marker_data_dict[color_id] = copy.deepcopy(marker_data_template)
marker_data_dict[color_id]["marker"]["color"] = color_id
marker_data_dict[color_id]["legendgroup"] = color_id
marker_data_dict[color_id]["x"].append(tasks[index]["x0"])
marker_data_dict[color_id]["x"].append(tasks[index]["x1"])
marker_data_dict[color_id]["y"].append(groupID)
marker_data_dict[color_id]["y"].append(groupID)
if "description" in tasks[index]:
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
del tasks[index]["description"]
else:
marker_data_dict[color_id]["text"].append(None)
marker_data_dict[color_id]["text"].append(None)
color_index += 1
showlegend = show_colorbar
layout = dict(
title=title,
showlegend=showlegend,
height=height,
width=width,
shapes=[],
hovermode="closest",
yaxis=dict(
showgrid=showgrid_y,
ticktext=task_names,
tickvals=list(range(len(task_names))),
range=[-1, len(task_names) + 1],
autorange=False,
zeroline=False,
),
xaxis=dict(
showgrid=showgrid_x,
zeroline=False,
rangeselector=dict(
buttons=list(
[
dict(count=7, label="1w", step="day", stepmode="backward"),
dict(count=1, label="1m", step="month", stepmode="backward"),
dict(count=6, label="6m", step="month", stepmode="backward"),
dict(count=1, label="YTD", step="year", stepmode="todate"),
dict(count=1, label="1y", step="year", stepmode="backward"),
dict(step="all"),
]
)
),
type="date",
),
)
data = [scatter_data_dict[k] for k in sorted(scatter_data_dict)]
data += [marker_data_dict[k] for k in sorted(marker_data_dict)]
# fig = dict(
# data=data, layout=layout
# )
fig = go.Figure(data=data, layout=layout)
return fig
def gantt_colorscale(
chart,
colors,
title,
index_col,
show_colorbar,
bar_width,
showgrid_x,
showgrid_y,
height,
width,
tasks=None,
task_names=None,
data=None,
group_tasks=False,
show_hover_fill=True,
):
"""
Refer to FigureFactory.create_gantt() for docstring
"""
if tasks is None:
tasks = []
if task_names is None:
task_names = []
if data is None:
data = []
showlegend = False
for index in range(len(chart)):
task = dict(
x0=chart[index]["Start"],
x1=chart[index]["Finish"],
name=chart[index]["Task"],
)
if "Description" in chart[index]:
task["description"] = chart[index]["Description"]
tasks.append(task)
# create a scatter trace for every task group
scatter_data_dict = dict()
# create scatter traces for the start- and endpoints
marker_data_dict = dict()
if show_hover_fill:
hoverinfo = "name"
else:
hoverinfo = "skip"
scatter_data_template = {
"x": [],
"y": [],
"mode": "none",
"fill": "toself",
"showlegend": False,
"hoverinfo": hoverinfo,
"legendgroup": "",
}
marker_data_template = {
"x": [],
"y": [],
"mode": "markers",
"text": [],
"marker": dict(color="", size=1, opacity=0),
"name": "",
"showlegend": False,
"legendgroup": "",
}
index_vals = []
for row in range(len(tasks)):
if chart[row][index_col] not in index_vals:
index_vals.append(chart[row][index_col])
index_vals.sort()
# compute the color for task based on indexing column
if isinstance(chart[0][index_col], Number):
# check that colors has at least 2 colors
if len(colors) < 2:
raise exceptions.PlotlyError(
"You must use at least 2 colors in 'colors' if you "
"are using a colorscale. However only the first two "
"colors given will be used for the lower and upper "
"bounds on the colormap."
)
# create the list of task names
for index in range(len(tasks)):
tn = tasks[index]["name"]
# Is added to task_names if group_tasks is set to False,
# or if the option is used (True) it only adds them if the
# name is not already in the list
if not group_tasks or tn not in task_names:
task_names.append(tn)
# Guarantees that for grouped tasks the tasks that are inserted
# first are shown at the top
if group_tasks:
task_names.reverse()
for index in range(len(tasks)):
tn = tasks[index]["name"]
del tasks[index]["name"]
# If group_tasks is True, all tasks with the same name belong
# to the same row.
groupID = index
if group_tasks:
groupID = task_names.index(tn)
tasks[index]["y0"] = groupID - bar_width
tasks[index]["y1"] = groupID + bar_width
# unlabel color
colors = clrs.color_parser(colors, clrs.unlabel_rgb)
lowcolor = colors[0]
highcolor = colors[1]
intermed = (chart[index][index_col]) / 100.0
intermed_color = clrs.find_intermediate_color(lowcolor, highcolor, intermed)
intermed_color = clrs.color_parser(intermed_color, clrs.label_rgb)
tasks[index]["fillcolor"] = intermed_color
color_id = tasks[index]["fillcolor"]
if color_id not in scatter_data_dict:
scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template)
scatter_data_dict[color_id]["fillcolor"] = color_id
scatter_data_dict[color_id]["name"] = str(chart[index][index_col])
scatter_data_dict[color_id]["legendgroup"] = color_id
# relabel colors with 'rgb'
colors = clrs.color_parser(colors, clrs.label_rgb)
# if there are already values append the gap
if len(scatter_data_dict[color_id]["x"]) > 0:
# a gap on the scatterplot separates the rectangles from each other
scatter_data_dict[color_id]["x"].append(
scatter_data_dict[color_id]["x"][-1]
)
scatter_data_dict[color_id]["y"].append(None)
xs, ys = _get_corner_points(
tasks[index]["x0"],
tasks[index]["y0"],
tasks[index]["x1"],
tasks[index]["y1"],
)
scatter_data_dict[color_id]["x"] += xs
scatter_data_dict[color_id]["y"] += ys
# append dummy markers for showing start and end of interval
if color_id not in marker_data_dict:
marker_data_dict[color_id] = copy.deepcopy(marker_data_template)
marker_data_dict[color_id]["marker"]["color"] = color_id
marker_data_dict[color_id]["legendgroup"] = color_id
marker_data_dict[color_id]["x"].append(tasks[index]["x0"])
marker_data_dict[color_id]["x"].append(tasks[index]["x1"])
marker_data_dict[color_id]["y"].append(groupID)
marker_data_dict[color_id]["y"].append(groupID)
if "description" in tasks[index]:
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
del tasks[index]["description"]
else:
marker_data_dict[color_id]["text"].append(None)
marker_data_dict[color_id]["text"].append(None)
# add colorbar to one of the traces randomly just for display
if show_colorbar is True:
k = list(marker_data_dict.keys())[0]
marker_data_dict[k]["marker"].update(
dict(
colorscale=[[0, colors[0]], [1, colors[1]]],
showscale=True,
cmax=100,
cmin=0,
)
)
if isinstance(chart[0][index_col], str):
index_vals = []
for row in range(len(tasks)):
if chart[row][index_col] not in index_vals:
index_vals.append(chart[row][index_col])
index_vals.sort()
if len(colors) < len(index_vals):
raise exceptions.PlotlyError(
"Error. The number of colors in 'colors' must be no less "
"than the number of unique index values in your group "
"column."
)
# make a dictionary assignment to each index value
index_vals_dict = {}
# define color index
c_index = 0
for key in index_vals:
if c_index > len(colors) - 1:
c_index = 0
index_vals_dict[key] = colors[c_index]
c_index += 1
# create the list of task names
for index in range(len(tasks)):
tn = tasks[index]["name"]
# Is added to task_names if group_tasks is set to False,
# or if the option is used (True) it only adds them if the
# name is not already in the list
if not group_tasks or tn not in task_names:
task_names.append(tn)
# Guarantees that for grouped tasks the tasks that are inserted
# first are shown at the top
if group_tasks:
task_names.reverse()
for index in range(len(tasks)):
tn = tasks[index]["name"]
del tasks[index]["name"]
# If group_tasks is True, all tasks with the same name belong
# to the same row.
groupID = index
if group_tasks:
groupID = task_names.index(tn)
tasks[index]["y0"] = groupID - bar_width
tasks[index]["y1"] = groupID + bar_width
tasks[index]["fillcolor"] = index_vals_dict[chart[index][index_col]]
color_id = tasks[index]["fillcolor"]
if color_id not in scatter_data_dict:
scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template)
scatter_data_dict[color_id]["fillcolor"] = color_id
scatter_data_dict[color_id]["legendgroup"] = color_id
scatter_data_dict[color_id]["name"] = str(chart[index][index_col])
# relabel colors with 'rgb'
colors = clrs.color_parser(colors, clrs.label_rgb)
# if there are already values append the gap
if len(scatter_data_dict[color_id]["x"]) > 0:
# a gap on the scatterplot separates the rectangles from each other
scatter_data_dict[color_id]["x"].append(
scatter_data_dict[color_id]["x"][-1]
)
scatter_data_dict[color_id]["y"].append(None)
xs, ys = _get_corner_points(
tasks[index]["x0"],
tasks[index]["y0"],
tasks[index]["x1"],
tasks[index]["y1"],
)
scatter_data_dict[color_id]["x"] += xs
scatter_data_dict[color_id]["y"] += ys
# append dummy markers for showing start and end of interval
if color_id not in marker_data_dict:
marker_data_dict[color_id] = copy.deepcopy(marker_data_template)
marker_data_dict[color_id]["marker"]["color"] = color_id
marker_data_dict[color_id]["legendgroup"] = color_id
marker_data_dict[color_id]["x"].append(tasks[index]["x0"])
marker_data_dict[color_id]["x"].append(tasks[index]["x1"])
marker_data_dict[color_id]["y"].append(groupID)
marker_data_dict[color_id]["y"].append(groupID)
if "description" in tasks[index]:
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
del tasks[index]["description"]
else:
marker_data_dict[color_id]["text"].append(None)
marker_data_dict[color_id]["text"].append(None)
if show_colorbar is True:
showlegend = True
for k in scatter_data_dict:
scatter_data_dict[k]["showlegend"] = showlegend
# add colorbar to one of the traces randomly just for display
# if show_colorbar is True:
# k = list(marker_data_dict.keys())[0]
# marker_data_dict[k]["marker"].update(
# dict(
# colorscale=[[0, colors[0]], [1, colors[1]]],
# showscale=True,
# cmax=100,
# cmin=0,
# )
# )
layout = dict(
title=title,
showlegend=showlegend,
height=height,
width=width,
shapes=[],
hovermode="closest",
yaxis=dict(
showgrid=showgrid_y,
ticktext=task_names,
tickvals=list(range(len(task_names))),
range=[-1, len(task_names) + 1],
autorange=False,
zeroline=False,
),
xaxis=dict(
showgrid=showgrid_x,
zeroline=False,
rangeselector=dict(
buttons=list(
[
dict(count=7, label="1w", step="day", stepmode="backward"),
dict(count=1, label="1m", step="month", stepmode="backward"),
dict(count=6, label="6m", step="month", stepmode="backward"),
dict(count=1, label="YTD", step="year", stepmode="todate"),
dict(count=1, label="1y", step="year", stepmode="backward"),
dict(step="all"),
]
)
),
type="date",
),
)
data = [scatter_data_dict[k] for k in sorted(scatter_data_dict)]
data += [marker_data_dict[k] for k in sorted(marker_data_dict)]
# fig = dict(
# data=data, layout=layout
# )
fig = go.Figure(data=data, layout=layout)
return fig
def gantt_dict(
chart,
colors,
title,
index_col,
show_colorbar,
bar_width,
showgrid_x,
showgrid_y,
height,
width,
tasks=None,
task_names=None,
data=None,
group_tasks=False,
show_hover_fill=True,
):
"""
Refer to FigureFactory.create_gantt() for docstring
"""
if tasks is None:
tasks = []
if task_names is None:
task_names = []
if data is None:
data = []
showlegend = False
for index in range(len(chart)):
task = dict(
x0=chart[index]["Start"],
x1=chart[index]["Finish"],
name=chart[index]["Task"],
)
if "Description" in chart[index]:
task["description"] = chart[index]["Description"]
tasks.append(task)
# create a scatter trace for every task group
scatter_data_dict = dict()
# create scatter traces for the start- and endpoints
marker_data_dict = dict()
if show_hover_fill:
hoverinfo = "name"
else:
hoverinfo = "skip"
scatter_data_template = {
"x": [],
"y": [],
"mode": "none",
"fill": "toself",
"hoverinfo": hoverinfo,
"legendgroup": "",
}
marker_data_template = {
"x": [],
"y": [],
"mode": "markers",
"text": [],
"marker": dict(color="", size=1, opacity=0),
"name": "",
"showlegend": False,
}
index_vals = []
for row in range(len(tasks)):
if chart[row][index_col] not in index_vals:
index_vals.append(chart[row][index_col])
index_vals.sort()
# verify each value in index column appears in colors dictionary
for key in index_vals:
if key not in colors:
raise exceptions.PlotlyError(
"If you are using colors as a dictionary, all of its "
"keys must be all the values in the index column."
)
# create the list of task names
for index in range(len(tasks)):
tn = tasks[index]["name"]
# Is added to task_names if group_tasks is set to False,
# or if the option is used (True) it only adds them if the
# name is not already in the list
if not group_tasks or tn not in task_names:
task_names.append(tn)
# Guarantees that for grouped tasks the tasks that are inserted first
# are shown at the top
if group_tasks:
task_names.reverse()
for index in range(len(tasks)):
tn = tasks[index]["name"]
del tasks[index]["name"]
# If group_tasks is True, all tasks with the same name belong
# to the same row.
groupID = index
if group_tasks:
groupID = task_names.index(tn)
tasks[index]["y0"] = groupID - bar_width
tasks[index]["y1"] = groupID + bar_width
tasks[index]["fillcolor"] = colors[chart[index][index_col]]
color_id = tasks[index]["fillcolor"]
if color_id not in scatter_data_dict:
scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template)
scatter_data_dict[color_id]["legendgroup"] = color_id
scatter_data_dict[color_id]["fillcolor"] = color_id
# if there are already values append the gap
if len(scatter_data_dict[color_id]["x"]) > 0:
# a gap on the scatterplot separates the rectangles from each other
scatter_data_dict[color_id]["x"].append(
scatter_data_dict[color_id]["x"][-1]
)
scatter_data_dict[color_id]["y"].append(None)
xs, ys = _get_corner_points(
tasks[index]["x0"],
tasks[index]["y0"],
tasks[index]["x1"],
tasks[index]["y1"],
)
scatter_data_dict[color_id]["x"] += xs
scatter_data_dict[color_id]["y"] += ys
# append dummy markers for showing start and end of interval
if color_id not in marker_data_dict:
marker_data_dict[color_id] = copy.deepcopy(marker_data_template)
marker_data_dict[color_id]["marker"]["color"] = color_id
marker_data_dict[color_id]["legendgroup"] = color_id
marker_data_dict[color_id]["x"].append(tasks[index]["x0"])
marker_data_dict[color_id]["x"].append(tasks[index]["x1"])
marker_data_dict[color_id]["y"].append(groupID)
marker_data_dict[color_id]["y"].append(groupID)
if "description" in tasks[index]:
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
marker_data_dict[color_id]["text"].append(tasks[index]["description"])
del tasks[index]["description"]
else:
marker_data_dict[color_id]["text"].append(None)
marker_data_dict[color_id]["text"].append(None)
if show_colorbar is True:
showlegend = True
for index_value in index_vals:
scatter_data_dict[colors[index_value]]["name"] = str(index_value)
layout = dict(
title=title,
showlegend=showlegend,
height=height,
width=width,
shapes=[],
hovermode="closest",
yaxis=dict(
showgrid=showgrid_y,
ticktext=task_names,
tickvals=list(range(len(task_names))),
range=[-1, len(task_names) + 1],
autorange=False,
zeroline=False,
),
xaxis=dict(
showgrid=showgrid_x,
zeroline=False,
rangeselector=dict(
buttons=list(
[
dict(count=7, label="1w", step="day", stepmode="backward"),
dict(count=1, label="1m", step="month", stepmode="backward"),
dict(count=6, label="6m", step="month", stepmode="backward"),
dict(count=1, label="YTD", step="year", stepmode="todate"),
dict(count=1, label="1y", step="year", stepmode="backward"),
dict(step="all"),
]
)
),
type="date",
),
)
data = [scatter_data_dict[k] for k in sorted(scatter_data_dict)]
data += [marker_data_dict[k] for k in sorted(marker_data_dict)]
# fig = dict(
# data=data, layout=layout
# )
fig = go.Figure(data=data, layout=layout)
return fig
def create_gantt(
df,
colors=None,
index_col=None,
show_colorbar=False,
reverse_colors=False,
title="Gantt Chart",
bar_width=0.2,
showgrid_x=False,
showgrid_y=False,
height=600,
width=None,
tasks=None,
task_names=None,
data=None,
group_tasks=False,
show_hover_fill=True,
):
"""
**deprecated**, use instead
:func:`plotly.express.timeline`.
Returns figure for a gantt chart
:param (array|list) df: input data for gantt chart. Must be either a
a dataframe or a list. If dataframe, the columns must include
'Task', 'Start' and 'Finish'. Other columns can be included and
used for indexing. If a list, its elements must be dictionaries
with the same required column headers: 'Task', 'Start' and
'Finish'.
:param (str|list|dict|tuple) colors: either a plotly scale name, an
rgb or hex color, a color tuple or a list of colors. An rgb color
is of the form 'rgb(x, y, z)' where x, y, z belong to the interval
[0, 255] and a color tuple is a tuple of the form (a, b, c) where
a, b and c belong to [0, 1]. If colors is a list, it must
contain the valid color types aforementioned as its members.
If a dictionary, all values of the indexing column must be keys in
colors.
:param (str|float) index_col: the column header (if df is a data
frame) that will function as the indexing column. If df is a list,
index_col must be one of the keys in all the items of df.
:param (bool) show_colorbar: determines if colorbar will be visible.
Only applies if values in the index column are numeric.
:param (bool) show_hover_fill: enables/disables the hovertext for the
filled area of the chart.
:param (bool) reverse_colors: reverses the order of selected colors
:param (str) title: the title of the chart
:param (float) bar_width: the width of the horizontal bars in the plot
:param (bool) showgrid_x: show/hide the x-axis grid
:param (bool) showgrid_y: show/hide the y-axis grid
:param (float) height: the height of the chart
:param (float) width: the width of the chart
Example 1: Simple Gantt Chart
>>> from plotly.figure_factory import create_gantt
>>> # Make data for chart
>>> df = [dict(Task="Job A", Start='2009-01-01', Finish='2009-02-30'),
... dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15'),
... dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30')]
>>> # Create a figure
>>> fig = create_gantt(df)
>>> fig.show()
Example 2: Index by Column with Numerical Entries
>>> from plotly.figure_factory import create_gantt
>>> # Make data for chart
>>> df = [dict(Task="Job A", Start='2009-01-01',
... Finish='2009-02-30', Complete=10),
... dict(Task="Job B", Start='2009-03-05',
... Finish='2009-04-15', Complete=60),
... dict(Task="Job C", Start='2009-02-20',
... Finish='2009-05-30', Complete=95)]
>>> # Create a figure with Plotly colorscale
>>> fig = create_gantt(df, colors='Blues', index_col='Complete',
... show_colorbar=True, bar_width=0.5,
... showgrid_x=True, showgrid_y=True)
>>> fig.show()
Example 3: Index by Column with String Entries
>>> from plotly.figure_factory import create_gantt
>>> # Make data for chart
>>> df = [dict(Task="Job A", Start='2009-01-01',
... Finish='2009-02-30', Resource='Apple'),
... dict(Task="Job B", Start='2009-03-05',
... Finish='2009-04-15', Resource='Grape'),
... dict(Task="Job C", Start='2009-02-20',
... Finish='2009-05-30', Resource='Banana')]
>>> # Create a figure with Plotly colorscale
>>> fig = create_gantt(df, colors=['rgb(200, 50, 25)', (1, 0, 1), '#6c4774'],
... index_col='Resource', reverse_colors=True,
... show_colorbar=True)
>>> fig.show()
Example 4: Use a dictionary for colors
>>> from plotly.figure_factory import create_gantt
>>> # Make data for chart
>>> df = [dict(Task="Job A", Start='2009-01-01',
... Finish='2009-02-30', Resource='Apple'),
... dict(Task="Job B", Start='2009-03-05',
... Finish='2009-04-15', Resource='Grape'),
... dict(Task="Job C", Start='2009-02-20',
... Finish='2009-05-30', Resource='Banana')]
>>> # Make a dictionary of colors
>>> colors = {'Apple': 'rgb(255, 0, 0)',
... 'Grape': 'rgb(170, 14, 200)',
... 'Banana': (1, 1, 0.2)}
>>> # Create a figure with Plotly colorscale
>>> fig = create_gantt(df, colors=colors, index_col='Resource',
... show_colorbar=True)
>>> fig.show()
Example 5: Use a pandas dataframe
>>> from plotly.figure_factory import create_gantt
>>> import pandas as pd
>>> # Make data as a dataframe
>>> df = pd.DataFrame([['Run', '2010-01-01', '2011-02-02', 10],
... ['Fast', '2011-01-01', '2012-06-05', 55],
... ['Eat', '2012-01-05', '2013-07-05', 94]],
... columns=['Task', 'Start', 'Finish', 'Complete'])
>>> # Create a figure with Plotly colorscale
>>> fig = create_gantt(df, colors='Blues', index_col='Complete',
... show_colorbar=True, bar_width=0.5,
... showgrid_x=True, showgrid_y=True)
>>> fig.show()
"""
# validate gantt input data
chart = validate_gantt(df)
if index_col:
if index_col not in chart[0]:
raise exceptions.PlotlyError(
"In order to use an indexing column and assign colors to "
"the values of the index, you must choose an actual "
"column name in the dataframe or key if a list of "
"dictionaries is being used."
)
# validate gantt index column
index_list = []
for dictionary in chart:
index_list.append(dictionary[index_col])
utils.validate_index(index_list)
# Validate colors
if isinstance(colors, dict):
colors = clrs.validate_colors_dict(colors, "rgb")
else:
colors = clrs.validate_colors(colors, "rgb")
if reverse_colors is True:
colors.reverse()
if not index_col:
if isinstance(colors, dict):
raise exceptions.PlotlyError(
"Error. You have set colors to a dictionary but have not "
"picked an index. An index is required if you are "
"assigning colors to particular values in a dictionary."
)
fig = gantt(
chart,
colors,
title,
bar_width,
showgrid_x,
showgrid_y,
height,
width,
tasks=None,
task_names=None,
data=None,
group_tasks=group_tasks,
show_hover_fill=show_hover_fill,
show_colorbar=show_colorbar,
)
return fig
else:
if not isinstance(colors, dict):
fig = gantt_colorscale(
chart,
colors,
title,
index_col,
show_colorbar,
bar_width,
showgrid_x,
showgrid_y,
height,
width,
tasks=None,
task_names=None,
data=None,
group_tasks=group_tasks,
show_hover_fill=show_hover_fill,
)
return fig
else:
fig = gantt_dict(
chart,
colors,
title,
index_col,
show_colorbar,
bar_width,
showgrid_x,
showgrid_y,
height,
width,
tasks=None,
task_names=None,
data=None,
group_tasks=group_tasks,
show_hover_fill=show_hover_fill,
)
return fig