diff --git a/packages../python../plotly../figure_factory../_gantt.py../issue1210 b/packages../python../plotly../figure_factory../_gantt.py../issue1210 new file mode 100644 index 00000000000..4cf5fb76bba --- /dev/null +++ b/packages../python../plotly../figure_factory../_gantt.py../issue1210 @@ -0,0 +1,1036 @@ +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, +): + """ + 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 + :param (str|list|dict|tuple) tasks: tasks to chart + :param (str|list|dict|tuple) task_names: task name that will be displayed on the chart + :param (bool) group_tasks: default=False. If true, tasks assigned the same task name will be charted in the same row. + + 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 dictioanry." + ) + 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