Ejemplo n.º 1
0
def validate_annotated_heatmap(z, x, y, annotation_text):
    """
    Annotated-heatmap-specific validations

    Check that if a text matrix is supplied, it has the same
    dimensions as the z matrix.

    See FigureFactory.create_annotated_heatmap() for params

    :raises: (PlotlyError) If z and text matrices do not  have the same
        dimensions.
    """
    if annotation_text is not None and isinstance(annotation_text, list):
        utils.validate_equal_length(z, annotation_text)
        for lst in range(len(z)):
            if len(z[lst]) != len(annotation_text[lst]):
                raise exceptions.PlotlyError("z and text should have the "
                                             "same dimensions")

    if x:
        if len(x) != len(z[0]):
            raise exceptions.PlotlyError("oops, the x list that you "
                                         "provided does not match the "
                                         "width of your z matrix ")

    if y:
        if len(y) != len(z):
            raise exceptions.PlotlyError("oops, the y list that you "
                                         "provided does not match the "
                                         "length of your z matrix ")
Ejemplo n.º 2
0
def validate_streamline(x, y):
    """
    Streamline-specific validations

    Specifically, this checks that x and y are both evenly spaced,
    and that the package numpy is available.

    See FigureFactory.create_streamline() for params

    :raises: (ImportError) If numpy is not available.
    :raises: (PlotlyError) If x is not evenly spaced.
    :raises: (PlotlyError) If y is not evenly spaced.
    """
    if np is False:
        raise ImportError("FigureFactory.create_streamline requires numpy")
    for index in range(len(x) - 1):
        if ((x[index + 1] - x[index]) - (x[1] - x[0])) > 0.0001:
            raise exceptions.PlotlyError(
                "x must be a 1 dimensional, " "evenly spaced array"
            )
    for index in range(len(y) - 1):
        if ((y[index + 1] - y[index]) - (y[1] - y[0])) > 0.0001:
            raise exceptions.PlotlyError(
                "y must be a 1 dimensional, " "evenly spaced array"
            )
Ejemplo n.º 3
0
def validate_distplot(hist_data, curve_type):
    """
    Distplot-specific validations

    :raises: (PlotlyError) If hist_data is not a list of lists
    :raises: (PlotlyError) If curve_type is not valid (i.e. not 'kde' or
        'normal').
    """
    hist_data_types = (list, )
    if np:
        hist_data_types += (np.ndarray, )
    if pd:
        hist_data_types += (pd.core.series.Series, )

    if not isinstance(hist_data[0], hist_data_types):
        raise exceptions.PlotlyError("Oops, this function was written "
                                     "to handle multiple datasets, if "
                                     "you want to plot just one, make "
                                     "sure your hist_data variable is "
                                     "still a list of lists, i.e. x = "
                                     "[1, 2, 3] -> x = [[1, 2, 3]]")

    curve_opts = ("kde", "normal")
    if curve_type not in curve_opts:
        raise exceptions.PlotlyError("curve_type must be defined as "
                                     "'kde' or 'normal'")

    if not scipy:
        raise ImportError("FigureFactory.create_distplot requires scipy")
Ejemplo n.º 4
0
def endpts_to_intervals(endpts):
    """
    Returns a list of intervals for categorical colormaps

    Accepts a list or tuple of sequentially increasing numbers and returns
    a list representation of the mathematical intervals with these numbers
    as endpoints. For example, [1, 6] returns [[-inf, 1], [1, 6], [6, inf]]

    :raises: (PlotlyError) If input is not a list or tuple
    :raises: (PlotlyError) If the input contains a string
    :raises: (PlotlyError) If any number does not increase after the
        previous one in the sequence
    """
    length = len(endpts)
    # Check if endpts is a list or tuple
    if not (isinstance(endpts, (tuple)) or isinstance(endpts, (list))):
        raise exceptions.PlotlyError(
            "The intervals_endpts argument must "
            "be a list or tuple of a sequence "
            "of increasing numbers."
        )
    # Check if endpts contains only numbers
    for item in endpts:
        if isinstance(item, str):
            raise exceptions.PlotlyError(
                "The intervals_endpts argument "
                "must be a list or tuple of a "
                "sequence of increasing "
                "numbers."
            )
    # Check if numbers in endpts are increasing
    for k in range(length - 1):
        if endpts[k] >= endpts[k + 1]:
            raise exceptions.PlotlyError(
                "The intervals_endpts argument "
                "must be a list or tuple of a "
                "sequence of increasing "
                "numbers."
            )
    else:
        intervals = []
        # add -inf to intervals
        intervals.append([float("-inf"), endpts[0]])
        for k in range(length - 1):
            interval = []
            interval.append(endpts[k])
            interval.append(endpts[k + 1])
            intervals.append(interval)
        # add +inf to intervals
        intervals.append([endpts[length - 1], float("inf")])
        return intervals
Ejemplo n.º 5
0
def _colors(ncontours, colormap=None):
    """
    Return a list of ``ncontours`` colors from the ``colormap`` colorscale.
    """
    if colormap in clrs.PLOTLY_SCALES.keys():
        cmap = clrs.PLOTLY_SCALES[colormap]
    else:
        raise exceptions.PlotlyError(
            "Colorscale must be a valid Plotly Colorscale."
            "The available colorscale names are {}".format(clrs.PLOTLY_SCALES.keys())
        )
    values = np.linspace(0, 1, ncontours)
    vals_cmap = np.array([pair[0] for pair in cmap])
    cols = np.array([pair[1] for pair in cmap])
    inds = np.searchsorted(vals_cmap, values)
    if "#" in cols[0]:  # for Viridis
        cols = [clrs.label_rgb(clrs.hex_to_rgb(col)) for col in cols]

    colors = [cols[0]]
    for ind, val in zip(inds[1:], values[1:]):
        val1, val2 = vals_cmap[ind - 1], vals_cmap[ind]
        interm = (val - val1) / (val2 - val1)
        col = clrs.find_intermediate_color(
            cols[ind - 1], cols[ind], interm, colortype="rgb"
        )
        colors.append(col)
    return colors
Ejemplo n.º 6
0
def validate_equal_length(*args):
    """
    Validates that data lists or ndarrays are the same length.

    :raises: (PlotlyError) If any data lists are not the same length.
    """
    length = len(args[0])
    if any(len(lst) != length for lst in args):
        raise exceptions.PlotlyError("Oops! Your data lists or ndarrays "
                                     "should be the same length.")
Ejemplo n.º 7
0
def validate_ohlc(open, high, low, close, direction, **kwargs):
    """
    ohlc and candlestick specific validations

    Specifically, this checks that the high value is the greatest value and
    the low value is the lowest value in each unit.

    See FigureFactory.create_ohlc() or FigureFactory.create_candlestick()
    for params

    :raises: (PlotlyError) If the high value is not the greatest value in
        each unit.
    :raises: (PlotlyError) If the low value is not the lowest value in each
        unit.
    :raises: (PlotlyError) If direction is not 'increasing' or 'decreasing'
    """
    for lst in [open, low, close]:
        for index in range(len(high)):
            if high[index] < lst[index]:
                raise exceptions.PlotlyError("Oops! Looks like some of "
                                             "your high values are less "
                                             "the corresponding open, "
                                             "low, or close values. "
                                             "Double check that your data "
                                             "is entered in O-H-L-C order")

    for lst in [open, high, close]:
        for index in range(len(low)):
            if low[index] > lst[index]:
                raise exceptions.PlotlyError("Oops! Looks like some of "
                                             "your low values are greater "
                                             "than the corresponding high"
                                             ", open, or close values. "
                                             "Double check that your data "
                                             "is entered in O-H-L-C order")

    direction_opts = ("increasing", "decreasing", "both")
    if direction not in direction_opts:
        raise exceptions.PlotlyError("direction must be defined as "
                                     "'increasing', 'decreasing', or "
                                     "'both'")
Ejemplo n.º 8
0
def return_figure_from_figure_or_data(figure_or_data, validate_figure):
    from plotly_study.graph_objs import Figure
    from plotly_study.basedatatypes import BaseFigure

    validated = False
    if isinstance(figure_or_data, dict):
        figure = figure_or_data
    elif isinstance(figure_or_data, list):
        figure = {"data": figure_or_data}
    elif isinstance(figure_or_data, BaseFigure):
        figure = figure_or_data.to_dict()
        validated = True
    else:
        raise exceptions.PlotlyError(
            "The `figure_or_data` positional "
            "argument must be "
            "`dict`-like, `list`-like, or an instance of plotly_study.graph_objs.Figure"
        )

    if validate_figure and not validated:

        try:
            figure = Figure(**figure).to_dict()
        except exceptions.PlotlyError as err:
            raise exceptions.PlotlyError("Invalid 'figure_or_data' argument. "
                                         "Plotly will not be able to properly "
                                         "parse the resulting JSON. If you "
                                         "want to send this 'figure_or_data' "
                                         "to Plotly anyway (not recommended), "
                                         "you can set 'validate=False' as a "
                                         "plot option.\nHere's why you're "
                                         "seeing this error:\n\n{0}"
                                         "".format(err))
        if not figure["data"]:
            raise exceptions.PlotlyEmptyDataError(
                "Empty data list found. Make sure that you populated the "
                "list of data objects you're sending and try again.\n"
                "Questions? Visit support.plot.ly")

    return figure
Ejemplo n.º 9
0
def validate_dataframe(array):
    """
    Validates all strings or numbers in each dataframe column

    :raises: (PlotlyError) If there are any two items in any list whose
        types differ
    """
    from numbers import Number

    for vector in array:
        if isinstance(vector[0], Number):
            if not all(isinstance(item, Number) for item in vector):
                raise exceptions.PlotlyError("Error in dataframe. "
                                             "Make sure all entries of "
                                             "each column are either "
                                             "numbers or strings.")
        elif isinstance(vector[0], str):
            if not all(isinstance(item, str) for item in vector):
                raise exceptions.PlotlyError("Error in dataframe. "
                                             "Make sure all entries of "
                                             "each column are either "
                                             "numbers or strings.")
Ejemplo n.º 10
0
def validate_index(index_vals):
    """
    Validates if a list contains all numbers or all strings

    :raises: (PlotlyError) If there are any two items in the list whose
        types differ
    """
    from numbers import Number

    if isinstance(index_vals[0], Number):
        if not all(isinstance(item, Number) for item in index_vals):
            raise exceptions.PlotlyError("Error in indexing column. "
                                         "Make sure all entries of each "
                                         "column are all numbers or "
                                         "all strings.")

    elif isinstance(index_vals[0], str):
        if not all(isinstance(item, str) for item in index_vals):
            raise exceptions.PlotlyError("Error in indexing column. "
                                         "Make sure all entries of each "
                                         "column are all numbers or "
                                         "all strings.")
Ejemplo n.º 11
0
def list_of_options(iterable, conj="and", period=True):
    """
    Returns an English listing of objects seperated by commas ','

    For example, ['foo', 'bar', 'baz'] becomes 'foo, bar and baz'
    if the conjunction 'and' is selected.
    """
    if len(iterable) < 2:
        raise exceptions.PlotlyError(
            "Your list or tuple must contain at least 2 items.")
    template = (len(iterable) -
                2) * "{}, " + "{} " + conj + " {}" + period * "."
    return template.format(*iterable)
Ejemplo n.º 12
0
def flatten(array):
    """
    Uses list comprehension to flatten array

    :param (array): An iterable to flatten
    :raises (PlotlyError): If iterable is not nested.
    :rtype (list): The flattened list.
    """
    try:
        return [item for sublist in array for item in sublist]
    except TypeError:
        raise exceptions.PlotlyError("Your data array could not be "
                                     "flattened! Make sure your data is "
                                     "entered as lists or ndarrays!")
Ejemplo n.º 13
0
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.ix[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
Ejemplo n.º 14
0
def validate_positive_scalars(**kwargs):
    """
    Validates that all values given in key/val pairs are positive.

    Accepts kwargs to improve Exception messages.

    :raises: (PlotlyError) If any value is < 0 or raises.
    """
    for key, val in kwargs.items():
        try:
            if val <= 0:
                raise ValueError("{} must be > 0, got {}".format(key, val))
        except TypeError:
            raise exceptions.PlotlyError("{} must be a number, got {}".format(
                key, val))
Ejemplo n.º 15
0
def validate_table(table_text, font_colors):
    """
    Table-specific validations

    Check that font_colors is supplied correctly (1, 3, or len(text)
        colors).

    :raises: (PlotlyError) If font_colors is supplied incorretly.

    See FigureFactory.create_table() for params
    """
    font_colors_len_options = [1, 3, len(table_text)]
    if len(font_colors) not in font_colors_len_options:
        raise exceptions.PlotlyError("Oops, font_colors should be a list "
                                     "of length 1, 3 or len(text)")
Ejemplo n.º 16
0
def get_graph_obj(obj, obj_type=None):
    """Returns a new graph object.

    OLD FUNCTION: this will *silently* strip out invalid pieces of the object.
    NEW FUNCTION: no striping of invalid pieces anymore - only raises error
        on unrecognized graph_objs
    """
    # TODO: Deprecate or move. #283
    from plotly_study.graph_objs import graph_objs

    try:
        cls = getattr(graph_objs, obj_type)
    except (AttributeError, KeyError):
        raise exceptions.PlotlyError(
            "'{}' is not a recognized graph_obj.".format(obj_type))
    return cls(obj)
Ejemplo n.º 17
0
def validate_scatterplotmatrix(df, index, diag, colormap_type, **kwargs):
    """
    Validates basic inputs for FigureFactory.create_scatterplotmatrix()

    :raises: (PlotlyError) If pandas is not imported
    :raises: (PlotlyError) If pandas dataframe is not inputted
    :raises: (PlotlyError) If pandas dataframe has <= 1 columns
    :raises: (PlotlyError) If diagonal plot choice (diag) is not one of
        the viable options
    :raises: (PlotlyError) If colormap_type is not a valid choice
    :raises: (PlotlyError) If kwargs contains 'size', 'color' or
        'colorscale'
    """
    if not pd:
        raise ImportError(
            "FigureFactory.scatterplotmatrix requires " "a pandas DataFrame."
        )

    # Check if pandas dataframe
    if not isinstance(df, pd.core.frame.DataFrame):
        raise exceptions.PlotlyError(
            "Dataframe not inputed. Please "
            "use a pandas dataframe to pro"
            "duce a scatterplot matrix."
        )

    # Check if dataframe is 1 column or less
    if len(df.columns) <= 1:
        raise exceptions.PlotlyError(
            "Dataframe has only one column. To "
            "use the scatterplot matrix, use at "
            "least 2 columns."
        )

    # Check that diag parameter is a valid selection
    if diag not in DIAG_CHOICES:
        raise exceptions.PlotlyError(
            "Make sure diag is set to " "one of {}".format(DIAG_CHOICES)
        )

    # Check that colormap_types is a valid selection
    if colormap_type not in VALID_COLORMAP_TYPES:
        raise exceptions.PlotlyError(
            "Must choose a valid colormap type. "
            "Either 'cat' or 'seq' for a cate"
            "gorical and sequential colormap "
            "respectively."
        )

    # Check for not 'size' or 'color' in 'marker' of **kwargs
    if "marker" in kwargs:
        FORBIDDEN_PARAMS = ["size", "color", "colorscale"]
        if any(param in kwargs["marker"] for param in FORBIDDEN_PARAMS):
            raise exceptions.PlotlyError(
                "Your kwargs dictionary cannot "
                "include the 'size', 'color' or "
                "'colorscale' key words inside "
                "the marker dict since 'size' is "
                "already an argument of the "
                "scatterplot matrix function and "
                "both 'color' and 'colorscale "
                "are set internally."
            )
Ejemplo n.º 18
0
def create_scatterplotmatrix(
    df,
    index=None,
    endpts=None,
    diag="scatter",
    height=500,
    width=500,
    size=6,
    title="Scatterplot Matrix",
    colormap=None,
    colormap_type="cat",
    dataframe=None,
    headers=None,
    index_vals=None,
    **kwargs
):
    """
    Returns data for a scatterplot matrix.

    :param (array) df: array of the data with column headers
    :param (str) index: name of the index column in data array
    :param (list|tuple) endpts: takes an increasing sequece of numbers
        that defines intervals on the real line. They are used to group
        the entries in an index of numbers into their corresponding
        interval and therefore can be treated as categorical data
    :param (str) diag: sets the chart type for the main diagonal plots.
        The options are 'scatter', 'histogram' and 'box'.
    :param (int|float) height: sets the height of the chart
    :param (int|float) width: sets the width of the chart
    :param (float) size: sets the marker size (in px)
    :param (str) title: the title label of the scatterplot matrix
    :param (str|tuple|list|dict) colormap: either a plotly scale name,
        an rgb or hex color, a color tuple, a list of colors or a
        dictionary. An rgb color is of the form 'rgb(x, y, z)' where
        x, y and 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 colormap is a list, it must contain valid color types as its
        members.
        If colormap is a dictionary, all the string entries in
        the index column must be a key in colormap. In this case, the
        colormap_type is forced to 'cat' or categorical
    :param (str) colormap_type: determines how colormap is interpreted.
        Valid choices are 'seq' (sequential) and 'cat' (categorical). If
        'seq' is selected, only the first two colors in colormap will be
        considered (when colormap is a list) and the index values will be
        linearly interpolated between those two colors. This option is
        forced if all index values are numeric.
        If 'cat' is selected, a color from colormap will be assigned to
        each category from index, including the intervals if endpts is
        being used
    :param (dict) **kwargs: a dictionary of scatterplot arguments
        The only forbidden parameters are 'size', 'color' and
        'colorscale' in 'marker'

    Example 1: Vanilla Scatterplot Matrix

    >>> from plotly_study.graph_objs import graph_objs
    >>> from plotly_study.figure_factory import create_scatterplotmatrix

    >>> import numpy as np
    >>> import pandas as pd

    >>> # Create dataframe
    >>> df = pd.DataFrame(np.random.randn(10, 2),
    ...                 columns=['Column 1', 'Column 2'])

    >>> # Create scatterplot matrix
    >>> fig = create_scatterplotmatrix(df)
    >>> fig.show()


    Example 2: Indexing a Column

    >>> from plotly_study.graph_objs import graph_objs
    >>> from plotly_study.figure_factory import create_scatterplotmatrix

    >>> import numpy as np
    >>> import pandas as pd

    >>> # Create dataframe with index
    >>> df = pd.DataFrame(np.random.randn(10, 2),
    ...                    columns=['A', 'B'])

    >>> # Add another column of strings to the dataframe
    >>> df['Fruit'] = pd.Series(['apple', 'apple', 'grape', 'apple', 'apple',
    ...                          'grape', 'pear', 'pear', 'apple', 'pear'])

    >>> # Create scatterplot matrix
    >>> fig = create_scatterplotmatrix(df, index='Fruit', size=10)
    >>> fig.show()


    Example 3: Styling the Diagonal Subplots

    >>> from plotly_study.graph_objs import graph_objs
    >>> from plotly_study.figure_factory import create_scatterplotmatrix

    >>> import numpy as np
    >>> import pandas as pd

    >>> # Create dataframe with index
    >>> df = pd.DataFrame(np.random.randn(10, 4),
    ...                    columns=['A', 'B', 'C', 'D'])

    >>> # Add another column of strings to the dataframe
    >>> df['Fruit'] = pd.Series(['apple', 'apple', 'grape', 'apple', 'apple',
    ...                          'grape', 'pear', 'pear', 'apple', 'pear'])

    >>> # Create scatterplot matrix
    >>> fig = create_scatterplotmatrix(df, diag='box', index='Fruit', height=1000,
    ...                                width=1000)
    >>> fig.show()


    Example 4: Use a Theme to Style the Subplots

    >>> from plotly_study.graph_objs import graph_objs
    >>> from plotly_study.figure_factory import create_scatterplotmatrix

    >>> import numpy as np
    >>> import pandas as pd

    >>> # Create dataframe with random data
    >>> df = pd.DataFrame(np.random.randn(100, 3),
    ...                    columns=['A', 'B', 'C'])

    >>> # Create scatterplot matrix using a built-in
    >>> # Plotly palette scale and indexing column 'A'
    >>> fig = create_scatterplotmatrix(df, diag='histogram', index='A',
    ...                                colormap='Blues', height=800, width=800)
    >>> fig.show()


    Example 5: Example 4 with Interval Factoring

    >>> from plotly_study.graph_objs import graph_objs
    >>> from plotly_study.figure_factory import create_scatterplotmatrix

    >>> import numpy as np
    >>> import pandas as pd

    >>> # Create dataframe with random data
    >>> df = pd.DataFrame(np.random.randn(100, 3),
    ...                    columns=['A', 'B', 'C'])

    >>> # Create scatterplot matrix using a list of 2 rgb tuples
    >>> # and endpoints at -1, 0 and 1
    >>> fig = create_scatterplotmatrix(df, diag='histogram', index='A',
    ...                                colormap=['rgb(140, 255, 50)',
    ...                                          'rgb(170, 60, 115)', '#6c4774',
    ...                                          (0.5, 0.1, 0.8)],
    ...                                endpts=[-1, 0, 1], height=800, width=800)
    >>> fig.show()


    Example 6: Using the colormap as a Dictionary

    >>> from plotly_study.graph_objs import graph_objs
    >>> from plotly_study.figure_factory import create_scatterplotmatrix

    >>> import numpy as np
    >>> import pandas as pd
    >>> import random

    >>> # Create dataframe with random data
    >>> df = pd.DataFrame(np.random.randn(100, 3),
    ...                    columns=['Column A',
    ...                             'Column B',
    ...                             'Column C'])

    >>> # Add new color column to dataframe
    >>> new_column = []
    >>> strange_colors = ['turquoise', 'limegreen', 'goldenrod']

    >>> for j in range(100):
    ...     new_column.append(random.choice(strange_colors))
    >>> df['Colors'] = pd.Series(new_column, index=df.index)

    >>> # Create scatterplot matrix using a dictionary of hex color values
    >>> # which correspond to actual color names in 'Colors' column
    >>> fig = create_scatterplotmatrix(
    ...     df, diag='box', index='Colors',
    ...     colormap= dict(
    ...         turquoise = '#00F5FF',
    ...         limegreen = '#32CD32',
    ...         goldenrod = '#DAA520'
    ...     ),
    ...     colormap_type='cat',
    ...     height=800, width=800
    ... )
    >>> fig.show()
    """
    # TODO: protected until #282
    if dataframe is None:
        dataframe = []
    if headers is None:
        headers = []
    if index_vals is None:
        index_vals = []

    validate_scatterplotmatrix(df, index, diag, colormap_type, **kwargs)

    # Validate colormap
    if isinstance(colormap, dict):
        colormap = clrs.validate_colors_dict(colormap, "rgb")
    elif (
        isinstance(colormap, six.string_types)
        and "rgb" not in colormap
        and "#" not in colormap
    ):
        if colormap not in clrs.PLOTLY_SCALES.keys():
            raise exceptions.PlotlyError(
                "If 'colormap' is a string, it must be the name "
                "of a Plotly Colorscale. The available colorscale "
                "names are {}".format(clrs.PLOTLY_SCALES.keys())
            )
        else:
            # TODO change below to allow the correct Plotly colorscale
            colormap = clrs.colorscale_to_colors(clrs.PLOTLY_SCALES[colormap])
            # keep only first and last item - fix later
            colormap = [colormap[0]] + [colormap[-1]]
        colormap = clrs.validate_colors(colormap, "rgb")
    else:
        colormap = clrs.validate_colors(colormap, "rgb")

    if not index:
        for name in df:
            headers.append(name)
        for name in headers:
            dataframe.append(df[name].values.tolist())
        # Check for same data-type in df columns
        utils.validate_dataframe(dataframe)
        figure = scatterplot(
            dataframe, headers, diag, size, height, width, title, **kwargs
        )
        return figure
    else:
        # Validate index selection
        if index not in df:
            raise exceptions.PlotlyError(
                "Make sure you set the index "
                "input variable to one of the "
                "column names of your "
                "dataframe."
            )
        index_vals = df[index].values.tolist()
        for name in df:
            if name != index:
                headers.append(name)
        for name in headers:
            dataframe.append(df[name].values.tolist())

        # check for same data-type in each df column
        utils.validate_dataframe(dataframe)
        utils.validate_index(index_vals)

        # check if all colormap keys are in the index
        # if colormap is a dictionary
        if isinstance(colormap, dict):
            for key in colormap:
                if not all(index in colormap for index in index_vals):
                    raise exceptions.PlotlyError(
                        "If colormap is a "
                        "dictionary, all the "
                        "names in the index "
                        "must be keys."
                    )
            figure = scatterplot_dict(
                dataframe,
                headers,
                diag,
                size,
                height,
                width,
                title,
                index,
                index_vals,
                endpts,
                colormap,
                colormap_type,
                **kwargs
            )
            return figure

        else:
            figure = scatterplot_theme(
                dataframe,
                headers,
                diag,
                size,
                height,
                width,
                title,
                index,
                index_vals,
                endpts,
                colormap,
                colormap_type,
                **kwargs
            )
            return figure
Ejemplo n.º 19
0
def create_facet_grid(df,
                      x=None,
                      y=None,
                      facet_row=None,
                      facet_col=None,
                      color_name=None,
                      colormap=None,
                      color_is_cat=False,
                      facet_row_labels=None,
                      facet_col_labels=None,
                      height=None,
                      width=None,
                      trace_type="scatter",
                      scales="fixed",
                      dtick_x=None,
                      dtick_y=None,
                      show_boxes=True,
                      ggplot2=False,
                      binsize=1,
                      **kwargs):
    """
    Returns figure for facet grid.

    :param (pd.DataFrame) df: the dataframe of columns for the facet grid.
    :param (str) x: the name of the dataframe column for the x axis data.
    :param (str) y: the name of the dataframe column for the y axis data.
    :param (str) facet_row: the name of the dataframe column that is used to
        facet the grid into row panels.
    :param (str) facet_col: the name of the dataframe column that is used to
        facet the grid into column panels.
    :param (str) color_name: the name of your dataframe column that will
        function as the colormap variable.
    :param (str|list|dict) colormap: the param that determines how the
        color_name column colors the data. If the dataframe contains numeric
        data, then a dictionary of colors will group the data categorically
        while a Plotly Colorscale name or a custom colorscale will treat it
        numerically. To learn more about colors and types of colormap, run
        `help(plotly_study.colors)`.
    :param (bool) color_is_cat: determines whether a numerical column for the
        colormap will be treated as categorical (True) or sequential (False).
            Default = False.
    :param (str|dict) facet_row_labels: set to either 'name' or a dictionary
        of all the unique values in the faceting row mapped to some text to
        show up in the label annotations. If None, labeling works like usual.
    :param (str|dict) facet_col_labels: set to either 'name' or a dictionary
        of all the values in the faceting row mapped to some text to show up
        in the label annotations. If None, labeling works like usual.
    :param (int) height: the height of the facet grid figure.
    :param (int) width: the width of the facet grid figure.
    :param (str) trace_type: decides the type of plot to appear in the
        facet grid. The options are 'scatter', 'scattergl', 'histogram',
        'bar', and 'box'.
        Default = 'scatter'.
    :param (str) scales: determines if axes have fixed ranges or not. Valid
        settings are 'fixed' (all axes fixed), 'free_x' (x axis free only),
        'free_y' (y axis free only) or 'free' (both axes free).
    :param (float) dtick_x: determines the distance between each tick on the
        x-axis. Default is None which means dtick_x is set automatically.
    :param (float) dtick_y: determines the distance between each tick on the
        y-axis. Default is None which means dtick_y is set automatically.
    :param (bool) show_boxes: draws grey boxes behind the facet titles.
    :param (bool) ggplot2: draws the facet grid in the style of `ggplot2`. See
        http://ggplot2.tidyverse.org/reference/facet_grid.html for reference.
        Default = False
    :param (int) binsize: groups all data into bins of a given length.
    :param (dict) kwargs: a dictionary of scatterplot arguments.

    Examples 1: One Way Faceting

    >>> import plotly_study.figure_factory as ff
    >>> import pandas as pd
    >>> mpg = pd.read_table('https://raw.githubusercontent.com/plotly/datasets/master/mpg_2017.txt')

    >>> fig = ff.create_facet_grid(
    ...     mpg,
    ...     x='displ',
    ...     y='cty',
    ...     facet_col='cyl',
    ... )
    >>> fig.show()

    Example 2: Two Way Faceting

    >>> import plotly_study.figure_factory as ff

    >>> import pandas as pd

    >>> mpg = pd.read_table('https://raw.githubusercontent.com/plotly/datasets/master/mpg_2017.txt')

    >>> fig = ff.create_facet_grid(
    ...     mpg,
    ...     x='displ',
    ...     y='cty',
    ...     facet_row='drv',
    ...     facet_col='cyl',
    ... )
    >>> fig.show()

    Example 3: Categorical Coloring

    >>> import plotly_study.figure_factory as ff
    >>> import pandas as pd
    >>> mpg = pd.read_table('https://raw.githubusercontent.com/plotly/datasets/master/mpg_2017.txt')
    >>> fig = ff.create_facet_grid(
    ...     mtcars,
    ...     x='mpg',
    ...     y='wt',
    ...     facet_col='cyl',
    ...     color_name='cyl',
    ...     color_is_cat=True,
    ... )
    >>> fig.show()

    Example 4: Sequential Coloring

    >>> import plotly_study.figure_factory as ff
    >>> import pandas as pd
    >>> tips = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/tips.csv')

    >>> fig = ff.create_facet_grid(
    >>>     tips,
    ...     x='total_bill',
    ...     y='tip',
    ...     facet_row='sex',
    ...     facet_col='smoker',
    ...     color_name='size',
    ...     colormap='Viridis',
    ... )
    >>> fig.show()

    Example 5: Custom labels

    >>> import plotly_study.figure_factory as ff
    >>> import pandas as pd
    >>> mtcars = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/mtcars.csv')
    >>> fig = ff.create_facet_grid(
    ...     mtcars,
    ...     x='wt',
    ...     y='mpg',
    ...     facet_col='cyl',
    ...     facet_col_labels={4: "$\\alpha$", 6: '$\\beta$', 8: '$\sqrt[y]{x}$'},
    ... )
    >>> fig.show()

    Example 6: Other Trace Type

    >>> import plotly_study.figure_factory as ff
    >>> import pandas as pd
    >>> mtcars = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/mtcars.csv')
    >>> fig = ff.create_facet_grid(
    ...     mtcars,
    ...     x='wt',
    ...     facet_col='cyl',
    ...     trace_type='histogram',
    ... )
    >>> fig.show()
    """
    if not pd:
        raise ImportError(
            "'pandas' must be installed for this figure_factory.")

    if not isinstance(df, pd.DataFrame):
        raise exceptions.PlotlyError("You must input a pandas DataFrame.")

    # make sure all columns are of homogenous datatype
    utils.validate_dataframe(df)

    if trace_type in ["scatter", "scattergl"]:
        if not x or not y:
            raise exceptions.PlotlyError(
                "You need to input 'x' and 'y' if you are you are using a "
                "trace_type of 'scatter' or 'scattergl'.")

    for key in [x, y, facet_row, facet_col, color_name]:
        if key is not None:
            try:
                df[key]
            except KeyError:
                raise exceptions.PlotlyError(
                    "x, y, facet_row, facet_col and color_name must be keys "
                    "in your dataframe.")
    # autoscale histogram bars
    if trace_type not in ["scatter", "scattergl"]:
        scales = "free"

    # validate scales
    if scales not in ["fixed", "free_x", "free_y", "free"]:
        raise exceptions.PlotlyError(
            "'scales' must be set to 'fixed', 'free_x', 'free_y' and 'free'.")

    if trace_type not in VALID_TRACE_TYPES:
        raise exceptions.PlotlyError(
            "'trace_type' must be in {}".format(VALID_TRACE_TYPES))

    if trace_type == "histogram":
        SUBPLOT_SPACING = 0.06
    else:
        SUBPLOT_SPACING = 0.015

    # seperate kwargs for marker and else
    if "marker" in kwargs:
        kwargs_marker = kwargs["marker"]
    else:
        kwargs_marker = {}
    marker_color = kwargs_marker.pop("color", None)
    kwargs.pop("marker", None)
    kwargs_trace = kwargs

    if "size" not in kwargs_marker:
        if ggplot2:
            kwargs_marker["size"] = 5
        else:
            kwargs_marker["size"] = 8

    if "opacity" not in kwargs_marker:
        if not ggplot2:
            kwargs_trace["opacity"] = 0.6

    if "line" not in kwargs_marker:
        if not ggplot2:
            kwargs_marker["line"] = {"color": "darkgrey", "width": 1}
        else:
            kwargs_marker["line"] = {}

    # default marker size
    if not ggplot2:
        if not marker_color:
            marker_color = "rgb(31, 119, 180)"
    else:
        marker_color = "rgb(0, 0, 0)"

    num_of_rows = 1
    num_of_cols = 1
    flipped_rows = False
    flipped_cols = False
    if facet_row:
        num_of_rows = len(df[facet_row].unique())
        flipped_rows = _is_flipped(num_of_rows)
        if isinstance(facet_row_labels, dict):
            for key in df[facet_row].unique():
                if key not in facet_row_labels.keys():
                    unique_keys = df[facet_row].unique().tolist()
                    raise exceptions.PlotlyError(
                        CUSTOM_LABEL_ERROR.format(unique_keys))
    if facet_col:
        num_of_cols = len(df[facet_col].unique())
        flipped_cols = _is_flipped(num_of_cols)
        if isinstance(facet_col_labels, dict):
            for key in df[facet_col].unique():
                if key not in facet_col_labels.keys():
                    unique_keys = df[facet_col].unique().tolist()
                    raise exceptions.PlotlyError(
                        CUSTOM_LABEL_ERROR.format(unique_keys))
    show_legend = False
    if color_name:
        if isinstance(df[color_name].iloc[0], str) or color_is_cat:
            show_legend = True
            if isinstance(colormap, dict):
                clrs.validate_colors_dict(colormap, "rgb")

                for val in df[color_name].unique():
                    if val not in colormap.keys():
                        raise exceptions.PlotlyError(
                            "If using 'colormap' as a dictionary, make sure "
                            "all the values of the colormap column are in "
                            "the keys of your dictionary.")
            else:
                # use default plotly colors for dictionary
                default_colors = clrs.DEFAULT_PLOTLY_COLORS
                colormap = {}
                j = 0
                for val in df[color_name].unique():
                    if j >= len(default_colors):
                        j = 0
                    colormap[val] = default_colors[j]
                    j += 1
            fig, annotations = _facet_grid_color_categorical(
                df,
                x,
                y,
                facet_row,
                facet_col,
                color_name,
                colormap,
                num_of_rows,
                num_of_cols,
                facet_row_labels,
                facet_col_labels,
                trace_type,
                flipped_rows,
                flipped_cols,
                show_boxes,
                SUBPLOT_SPACING,
                marker_color,
                kwargs_trace,
                kwargs_marker,
            )

        elif isinstance(df[color_name].iloc[0], Number):
            if isinstance(colormap, dict):
                show_legend = True
                clrs.validate_colors_dict(colormap, "rgb")

                for val in df[color_name].unique():
                    if val not in colormap.keys():
                        raise exceptions.PlotlyError(
                            "If using 'colormap' as a dictionary, make sure "
                            "all the values of the colormap column are in "
                            "the keys of your dictionary.")
                fig, annotations = _facet_grid_color_categorical(
                    df,
                    x,
                    y,
                    facet_row,
                    facet_col,
                    color_name,
                    colormap,
                    num_of_rows,
                    num_of_cols,
                    facet_row_labels,
                    facet_col_labels,
                    trace_type,
                    flipped_rows,
                    flipped_cols,
                    show_boxes,
                    SUBPLOT_SPACING,
                    marker_color,
                    kwargs_trace,
                    kwargs_marker,
                )

            elif isinstance(colormap, list):
                colorscale_list = colormap
                clrs.validate_colorscale(colorscale_list)

                fig, annotations = _facet_grid_color_numerical(
                    df,
                    x,
                    y,
                    facet_row,
                    facet_col,
                    color_name,
                    colorscale_list,
                    num_of_rows,
                    num_of_cols,
                    facet_row_labels,
                    facet_col_labels,
                    trace_type,
                    flipped_rows,
                    flipped_cols,
                    show_boxes,
                    SUBPLOT_SPACING,
                    marker_color,
                    kwargs_trace,
                    kwargs_marker,
                )
            elif isinstance(colormap, str):
                if colormap in clrs.PLOTLY_SCALES.keys():
                    colorscale_list = clrs.PLOTLY_SCALES[colormap]
                else:
                    raise exceptions.PlotlyError(
                        "If 'colormap' is a string, it must be the name "
                        "of a Plotly Colorscale. The available colorscale "
                        "names are {}".format(clrs.PLOTLY_SCALES.keys()))
                fig, annotations = _facet_grid_color_numerical(
                    df,
                    x,
                    y,
                    facet_row,
                    facet_col,
                    color_name,
                    colorscale_list,
                    num_of_rows,
                    num_of_cols,
                    facet_row_labels,
                    facet_col_labels,
                    trace_type,
                    flipped_rows,
                    flipped_cols,
                    show_boxes,
                    SUBPLOT_SPACING,
                    marker_color,
                    kwargs_trace,
                    kwargs_marker,
                )
            else:
                colorscale_list = clrs.PLOTLY_SCALES["Reds"]
                fig, annotations = _facet_grid_color_numerical(
                    df,
                    x,
                    y,
                    facet_row,
                    facet_col,
                    color_name,
                    colorscale_list,
                    num_of_rows,
                    num_of_cols,
                    facet_row_labels,
                    facet_col_labels,
                    trace_type,
                    flipped_rows,
                    flipped_cols,
                    show_boxes,
                    SUBPLOT_SPACING,
                    marker_color,
                    kwargs_trace,
                    kwargs_marker,
                )

    else:
        fig, annotations = _facet_grid(
            df,
            x,
            y,
            facet_row,
            facet_col,
            num_of_rows,
            num_of_cols,
            facet_row_labels,
            facet_col_labels,
            trace_type,
            flipped_rows,
            flipped_cols,
            show_boxes,
            SUBPLOT_SPACING,
            marker_color,
            kwargs_trace,
            kwargs_marker,
        )

    if not height:
        height = max(600, 100 * num_of_rows)
    if not width:
        width = max(600, 100 * num_of_cols)

    fig["layout"].update(height=height,
                         width=width,
                         title="",
                         paper_bgcolor="rgb(251, 251, 251)")
    if ggplot2:
        fig["layout"].update(
            plot_bgcolor=PLOT_BGCOLOR,
            paper_bgcolor="rgb(255, 255, 255)",
            hovermode="closest",
        )

    # axis titles
    x_title_annot = _axis_title_annotation(x, "x")
    y_title_annot = _axis_title_annotation(y, "y")

    # annotations
    annotations.append(x_title_annot)
    annotations.append(y_title_annot)

    # legend
    fig["layout"]["showlegend"] = show_legend
    fig["layout"]["legend"]["bgcolor"] = LEGEND_COLOR
    fig["layout"]["legend"]["borderwidth"] = LEGEND_BORDER_WIDTH
    fig["layout"]["legend"]["x"] = 1.05
    fig["layout"]["legend"]["y"] = 1
    fig["layout"]["legend"]["yanchor"] = "top"

    if show_legend:
        fig["layout"]["showlegend"] = show_legend
        if ggplot2:
            if color_name:
                legend_annot = _legend_annotation(color_name)
                annotations.append(legend_annot)
            fig["layout"]["margin"]["r"] = 150

    # assign annotations to figure
    fig["layout"]["annotations"] = annotations

    # add shaded boxes behind axis titles
    if show_boxes and ggplot2:
        _add_shapes_to_fig(fig, ANNOT_RECT_COLOR, flipped_rows, flipped_cols)

    # all xaxis and yaxis labels
    axis_labels = {"x": [], "y": []}
    for key in fig["layout"]:
        if "xaxis" in key:
            axis_labels["x"].append(key)
        elif "yaxis" in key:
            axis_labels["y"].append(key)

    string_number_in_data = False
    for var in [v for v in [x, y] if v]:
        if isinstance(df[var].tolist()[0], str):
            for item in df[var]:
                try:
                    int(item)
                    string_number_in_data = True
                except ValueError:
                    pass

    if string_number_in_data:
        for x_y in axis_labels.keys():
            for axis_name in axis_labels[x_y]:
                fig["layout"][axis_name]["type"] = "category"

    if scales == "fixed":
        fixed_axes = ["x", "y"]
    elif scales == "free_x":
        fixed_axes = ["y"]
    elif scales == "free_y":
        fixed_axes = ["x"]
    elif scales == "free":
        fixed_axes = []

    # fixed ranges
    for x_y in fixed_axes:
        min_ranges = []
        max_ranges = []
        for trace in fig["data"]:
            if trace[x_y] is not None and len(trace[x_y]) > 0:
                min_ranges.append(min(trace[x_y]))
                max_ranges.append(max(trace[x_y]))
        while None in min_ranges:
            min_ranges.remove(None)
        while None in max_ranges:
            max_ranges.remove(None)

        min_range = min(min_ranges)
        max_range = max(max_ranges)

        range_are_numbers = isinstance(min_range, Number) and isinstance(
            max_range, Number)

        if range_are_numbers:
            min_range = math.floor(min_range)
            max_range = math.ceil(max_range)

            # extend widen frame by 5% on each side
            min_range -= 0.05 * (max_range - min_range)
            max_range += 0.05 * (max_range - min_range)

            if x_y == "x":
                if dtick_x:
                    dtick = dtick_x
                else:
                    dtick = math.floor(
                        (max_range - min_range) / MAX_TICKS_PER_AXIS)
            elif x_y == "y":
                if dtick_y:
                    dtick = dtick_y
                else:
                    dtick = math.floor(
                        (max_range - min_range) / MAX_TICKS_PER_AXIS)
        else:
            dtick = 1

        for axis_title in axis_labels[x_y]:
            fig["layout"][axis_title]["dtick"] = dtick
            fig["layout"][axis_title]["ticklen"] = 0
            fig["layout"][axis_title]["zeroline"] = False
            if ggplot2:
                fig["layout"][axis_title]["tickwidth"] = 1
                fig["layout"][axis_title]["ticklen"] = 4
                fig["layout"][axis_title]["gridwidth"] = GRID_WIDTH

                fig["layout"][axis_title]["gridcolor"] = GRID_COLOR
                fig["layout"][axis_title]["gridwidth"] = 2
                fig["layout"][axis_title]["tickfont"] = {
                    "color": TICK_COLOR,
                    "size": 10,
                }

        # insert ranges into fig
        if x_y in fixed_axes:
            for key in fig["layout"]:
                if "{}axis".format(x_y) in key and range_are_numbers:
                    fig["layout"][key]["range"] = [min_range, max_range]

    return fig
Ejemplo n.º 20
0
def map_face2color(face, colormap, scale, vmin, vmax):
    """
    Normalize facecolor values by vmin/vmax and return rgb-color strings

    This function takes a tuple color along with a colormap and a minimum
    (vmin) and maximum (vmax) range of possible mean distances for the
    given parametrized surface. It returns an rgb color based on the mean
    distance between vmin and vmax

    """
    if vmin >= vmax:
        raise exceptions.PlotlyError(
            "Incorrect relation between vmin "
            "and vmax. The vmin value cannot be "
            "bigger than or equal to the value "
            "of vmax."
        )
    if len(colormap) == 1:
        # color each triangle face with the same color in colormap
        face_color = colormap[0]
        face_color = clrs.convert_to_RGB_255(face_color)
        face_color = clrs.label_rgb(face_color)
        return face_color
    if face == vmax:
        # pick last color in colormap
        face_color = colormap[-1]
        face_color = clrs.convert_to_RGB_255(face_color)
        face_color = clrs.label_rgb(face_color)
        return face_color
    else:
        if scale is None:
            # find the normalized distance t of a triangle face between
            # vmin and vmax where the distance is between 0 and 1
            t = (face - vmin) / float((vmax - vmin))
            low_color_index = int(t / (1.0 / (len(colormap) - 1)))

            face_color = clrs.find_intermediate_color(
                colormap[low_color_index],
                colormap[low_color_index + 1],
                t * (len(colormap) - 1) - low_color_index,
            )

            face_color = clrs.convert_to_RGB_255(face_color)
            face_color = clrs.label_rgb(face_color)
        else:
            # find the face color for a non-linearly interpolated scale
            t = (face - vmin) / float((vmax - vmin))

            low_color_index = 0
            for k in range(len(scale) - 1):
                if scale[k] <= t < scale[k + 1]:
                    break
                low_color_index += 1

            low_scale_val = scale[low_color_index]
            high_scale_val = scale[low_color_index + 1]

            face_color = clrs.find_intermediate_color(
                colormap[low_color_index],
                colormap[low_color_index + 1],
                (t - low_scale_val) / (high_scale_val - low_scale_val),
            )

            face_color = clrs.convert_to_RGB_255(face_color)
            face_color = clrs.label_rgb(face_color)
        return face_color
Ejemplo n.º 21
0
def create_violin(
    data,
    data_header=None,
    group_header=None,
    colors=None,
    use_colorscale=False,
    group_stats=None,
    rugplot=True,
    sort=False,
    height=450,
    width=600,
    title="Violin and Rug Plot",
):
    """
    Returns figure for a violin plot

    :param (list|array) data: accepts either a list of numerical values,
        a list of dictionaries all with identical keys and at least one
        column of numeric values, or a pandas dataframe with at least one
        column of numbers.
    :param (str) data_header: the header of the data column to be used
        from an inputted pandas dataframe. Not applicable if 'data' is
        a list of numeric values.
    :param (str) group_header: applicable if grouping data by a variable.
        'group_header' must be set to the name of the grouping variable.
    :param (str|tuple|list|dict) colors: either a plotly scale name,
        an rgb or hex color, a color tuple, a list of colors or a
        dictionary. An rgb color is of the form 'rgb(x, y, z)' where
        x, y and 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 valid color types as its
        members.
    :param (bool) use_colorscale: only applicable if grouping by another
        variable. Will implement a colorscale based on the first 2 colors
        of param colors. This means colors must be a list with at least 2
        colors in it (Plotly colorscales are accepted since they map to a
        list of two rgb colors). Default = False
    :param (dict) group_stats: a dictioanry where each key is a unique
        value from the group_header column in data. Each value must be a
        number and will be used to color the violin plots if a colorscale
        is being used.
    :param (bool) rugplot: determines if a rugplot is draw on violin plot.
        Default = True
    :param (bool) sort: determines if violins are sorted
        alphabetically (True) or by input order (False). Default = False
    :param (float) height: the height of the violin plot.
    :param (float) width: the width of the violin plot.
    :param (str) title: the title of the violin plot.

    Example 1: Single Violin Plot

    >>> from plotly_study.figure_factory import create_violin
    >>> import plotly_study.graph_objs as graph_objects

    >>> import numpy as np
    >>> from scipy import stats

    >>> # create list of random values
    >>> data_list = np.random.randn(100)
    >>> data_list.tolist()

    >>> # create violin fig
    >>> fig = create_violin(data_list, colors='#604d9e')

    >>> # plot
    >>> fig.show()

    Example 2: Multiple Violin Plots with Qualitative Coloring

    >>> from plotly_study.figure_factory import create_violin
    >>> import plotly_study.graph_objs as graph_objects

    >>> import numpy as np
    >>> import pandas as pd
    >>> from scipy import stats

    >>> # create dataframe
    >>> np.random.seed(619517)
    >>> Nr=250
    >>> y = np.random.randn(Nr)
    >>> gr = np.random.choice(list("ABCDE"), Nr)
    >>> norm_params=[(0, 1.2), (0.7, 1), (-0.5, 1.4), (0.3, 1), (0.8, 0.9)]

    >>> for i, letter in enumerate("ABCDE"):
    ...     y[gr == letter] *=norm_params[i][1]+ norm_params[i][0]
    >>> df = pd.DataFrame(dict(Score=y, Group=gr))

    >>> # create violin fig
    >>> fig = create_violin(df, data_header='Score', group_header='Group',
    ...                    sort=True, height=600, width=1000)

    >>> # plot
    >>> fig.show()

    Example 3: Violin Plots with Colorscale

    >>> from plotly_study.figure_factory import create_violin
    >>> import plotly_study.graph_objs as graph_objects

    >>> import numpy as np
    >>> import pandas as pd
    >>> from scipy import stats

    >>> # create dataframe
    >>> np.random.seed(619517)
    >>> Nr=250
    >>> y = np.random.randn(Nr)
    >>> gr = np.random.choice(list("ABCDE"), Nr)
    >>> norm_params=[(0, 1.2), (0.7, 1), (-0.5, 1.4), (0.3, 1), (0.8, 0.9)]

    >>> for i, letter in enumerate("ABCDE"):
    ...     y[gr == letter] *=norm_params[i][1]+ norm_params[i][0]
    >>> df = pd.DataFrame(dict(Score=y, Group=gr))

    >>> # define header params
    >>> data_header = 'Score'
    >>> group_header = 'Group'

    >>> # make groupby object with pandas
    >>> group_stats = {}
    >>> groupby_data = df.groupby([group_header])

    >>> for group in "ABCDE":
    ...     data_from_group = groupby_data.get_group(group)[data_header]
    ...     # take a stat of the grouped data
    ...     stat = np.median(data_from_group)
    ...     # add to dictionary
    ...     group_stats[group] = stat

    >>> # create violin fig
    >>> fig = create_violin(df, data_header='Score', group_header='Group',
    ...                     height=600, width=1000, use_colorscale=True,
    ...                     group_stats=group_stats)

    >>> # plot
    >>> fig.show()
    """

    # Validate colors
    if isinstance(colors, dict):
        valid_colors = clrs.validate_colors_dict(colors, "rgb")
    else:
        valid_colors = clrs.validate_colors(colors, "rgb")

    # validate data and choose plot type
    if group_header is None:
        if isinstance(data, list):
            if len(data) <= 0:
                raise exceptions.PlotlyError("If data is a list, it must be "
                                             "nonempty and contain either "
                                             "numbers or dictionaries.")

            if not all(isinstance(element, Number) for element in data):
                raise exceptions.PlotlyError("If data is a list, it must "
                                             "contain only numbers.")

        if pd and isinstance(data, pd.core.frame.DataFrame):
            if data_header is None:
                raise exceptions.PlotlyError("data_header must be the "
                                             "column name with the "
                                             "desired numeric data for "
                                             "the violin plot.")

            data = data[data_header].values.tolist()

        # call the plotting functions
        plot_data, plot_xrange = violinplot(data,
                                            fillcolor=valid_colors[0],
                                            rugplot=rugplot)

        layout = graph_objs.Layout(
            title=title,
            autosize=False,
            font=graph_objs.layout.Font(size=11),
            height=height,
            showlegend=False,
            width=width,
            xaxis=make_XAxis("", plot_xrange),
            yaxis=make_YAxis(""),
            hovermode="closest",
        )
        layout["yaxis"].update(
            dict(showline=False, showticklabels=False, ticks=""))

        fig = graph_objs.Figure(data=plot_data, layout=layout)

        return fig

    else:
        if not isinstance(data, pd.core.frame.DataFrame):
            raise exceptions.PlotlyError("Error. You must use a pandas "
                                         "DataFrame if you are using a "
                                         "group header.")

        if data_header is None:
            raise exceptions.PlotlyError("data_header must be the column "
                                         "name with the desired numeric "
                                         "data for the violin plot.")

        if use_colorscale is False:
            if isinstance(valid_colors, dict):
                # validate colors dict choice below
                fig = violin_dict(
                    data,
                    data_header,
                    group_header,
                    valid_colors,
                    use_colorscale,
                    group_stats,
                    rugplot,
                    sort,
                    height,
                    width,
                    title,
                )
                return fig
            else:
                fig = violin_no_colorscale(
                    data,
                    data_header,
                    group_header,
                    valid_colors,
                    use_colorscale,
                    group_stats,
                    rugplot,
                    sort,
                    height,
                    width,
                    title,
                )
                return fig
        else:
            if isinstance(valid_colors, dict):
                raise exceptions.PlotlyError("The colors param cannot be "
                                             "a dictionary if you are "
                                             "using a colorscale.")

            if len(valid_colors) < 2:
                raise exceptions.PlotlyError("colors must be a list with "
                                             "at least 2 colors. A "
                                             "Plotly scale is allowed.")

            if not isinstance(group_stats, dict):
                raise exceptions.PlotlyError("Your group_stats param "
                                             "must be a dictionary.")

            fig = violin_colorscale(
                data,
                data_header,
                group_header,
                valid_colors,
                use_colorscale,
                group_stats,
                rugplot,
                sort,
                height,
                width,
                title,
            )
            return fig
Ejemplo n.º 22
0
def create_bullet(data,
                  markers=None,
                  measures=None,
                  ranges=None,
                  subtitles=None,
                  titles=None,
                  orientation="h",
                  range_colors=("rgb(200, 200, 200)", "rgb(245, 245, 245)"),
                  measure_colors=("rgb(31, 119, 180)", "rgb(176, 196, 221)"),
                  horizontal_spacing=None,
                  vertical_spacing=None,
                  scatter_options={},
                  **layout_options):
    """
    Returns figure for bullet chart.

    :param (pd.DataFrame | list | tuple) data: either a list/tuple of
        dictionaries or a pandas DataFrame.
    :param (str) markers: the column name or dictionary key for the markers in
        each subplot.
    :param (str) measures: the column name or dictionary key for the measure
        bars in each subplot. This bar usually represents the quantitative
        measure of performance, usually a list of two values [a, b] and are
        the blue bars in the foreground of each subplot by default.
    :param (str) ranges: the column name or dictionary key for the qualitative
        ranges of performance, usually a 3-item list [bad, okay, good]. They
        correspond to the grey bars in the background of each chart.
    :param (str) subtitles: the column name or dictionary key for the subtitle
        of each subplot chart. The subplots are displayed right underneath
        each title.
    :param (str) titles: the column name or dictionary key for the main label
        of each subplot chart.
    :param (bool) orientation: if 'h', the bars are placed horizontally as
        rows. If 'v' the bars are placed vertically in the chart.
    :param (list) range_colors: a tuple of two colors between which all
        the rectangles for the range are drawn. These rectangles are meant to
        be qualitative indicators against which the marker and measure bars
        are compared.
        Default=('rgb(200, 200, 200)', 'rgb(245, 245, 245)')
    :param (list) measure_colors: a tuple of two colors which is used to color
        the thin quantitative bars in the bullet chart.
        Default=('rgb(31, 119, 180)', 'rgb(176, 196, 221)')
    :param (float) horizontal_spacing: see the 'horizontal_spacing' param in
        plotly_study.tools.make_subplots. Ranges between 0 and 1.
    :param (float) vertical_spacing: see the 'vertical_spacing' param in
        plotly_study.tools.make_subplots. Ranges between 0 and 1.
    :param (dict) scatter_options: describes attributes for the scatter trace
        in each subplot such as name and marker size. Call
        help(plotly_study.graph_objs.Scatter) for more information on valid params.
    :param layout_options: describes attributes for the layout of the figure
        such as title, height and width. Call help(plotly_study.graph_objs.Layout)
        for more information on valid params.

    Example 1: Use a Dictionary
    
    >>> import plotly_study.figure_factory as ff

    >>> data = [
    ...   {"label": "revenue", "sublabel": "us$, in thousands",
    ...    "range": [150, 225, 300], "performance": [220,270], "point": [250]},
    ...   {"label": "Profit", "sublabel": "%", "range": [20, 25, 30],
    ...    "performance": [21, 23], "point": [26]},
    ...   {"label": "Order Size", "sublabel":"US$, average","range": [350, 500, 600],
    ...    "performance": [100,320],"point": [550]},
    ...   {"label": "New Customers", "sublabel": "count", "range": [1400, 2000, 2500],
    ...    "performance": [1000, 1650],"point": [2100]},
    ...   {"label": "Satisfaction", "sublabel": "out of 5","range": [3.5, 4.25, 5],
    ...    "performance": [3.2, 4.7], "point": [4.4]}
    ... ]

    >>> fig = ff.create_bullet(
    ...     data, titles='label', subtitles='sublabel', markers='point',
    ...     measures='performance', ranges='range', orientation='h',
    ...     title='my simple bullet chart'
    ... )
    >>> fig.show()

    Example 2: Use a DataFrame with Custom Colors

    >>> import plotly_study.figure_factory as ff
    >>> import pandas as pd
    >>> data = pd.read_json('https://cdn.rawgit.com/plotly/datasets/master/BulletData.json')

    >>> fig = ff.create_bullet(
    ...     data, titles='title', markers='markers', measures='measures',
    ...     orientation='v', measure_colors=['rgb(14, 52, 75)', 'rgb(31, 141, 127)'],
    ...     scatter_options={'marker': {'symbol': 'circle'}}, width=700)
    >>> fig.show()
    """
    # validate df
    if not pd:
        raise ImportError(
            "'pandas' must be installed for this figure factory.")

    if utils.is_sequence(data):
        if not all(isinstance(item, dict) for item in data):
            raise exceptions.PlotlyError(
                "Every entry of the data argument list, tuple, etc must "
                "be a dictionary.")

    elif not isinstance(data, pd.DataFrame):
        raise exceptions.PlotlyError(
            "You must input a pandas DataFrame, or a list of dictionaries.")

    # make DataFrame from data with correct column headers
    col_names = ["titles", "subtitle", "markers", "measures", "ranges"]
    if utils.is_sequence(data):
        df = pd.DataFrame(
            [
                [d[titles] for d in data] if titles else [""] * len(data),
                [d[subtitles]
                 for d in data] if subtitles else [""] * len(data),
                [d[markers] for d in data] if markers else [[]] * len(data),
                [d[measures] for d in data] if measures else [[]] * len(data),
                [d[ranges] for d in data] if ranges else [[]] * len(data),
            ],
            index=col_names,
        )
    elif isinstance(data, pd.DataFrame):
        df = pd.DataFrame(
            [
                data[titles].tolist() if titles else [""] * len(data),
                data[subtitles].tolist() if subtitles else [""] * len(data),
                data[markers].tolist() if markers else [[]] * len(data),
                data[measures].tolist() if measures else [[]] * len(data),
                data[ranges].tolist() if ranges else [[]] * len(data),
            ],
            index=col_names,
        )
    df = pd.DataFrame.transpose(df)

    # make sure ranges, measures, 'markers' are not NAN or NONE
    for needed_key in ["ranges", "measures", "markers"]:
        for idx, r in enumerate(df[needed_key]):
            try:
                r_is_nan = math.isnan(r)
                if r_is_nan or r is None:
                    df[needed_key][idx] = []
            except TypeError:
                pass

    # validate custom colors
    for colors_list in [range_colors, measure_colors]:
        if colors_list:
            if len(colors_list) != 2:
                raise exceptions.PlotlyError(
                    "Both 'range_colors' or 'measure_colors' must be a list "
                    "of two valid colors.")
            clrs.validate_colors(colors_list)
            colors_list = clrs.convert_colors_to_same_type(colors_list,
                                                           "rgb")[0]

    # default scatter options
    default_scatter = {
        "marker": {
            "size": 12,
            "symbol": "diamond-tall",
            "color": "rgb(0, 0, 0)"
        }
    }

    if scatter_options == {}:
        scatter_options.update(default_scatter)
    else:
        # add default options to scatter_options if they are not present
        for k in default_scatter["marker"]:
            if k not in scatter_options["marker"]:
                scatter_options["marker"][k] = default_scatter["marker"][k]

    fig = _bullet(
        df,
        markers,
        measures,
        ranges,
        subtitles,
        titles,
        orientation,
        range_colors,
        measure_colors,
        horizontal_spacing,
        vertical_spacing,
        scatter_options,
        layout_options,
    )

    return fig
Ejemplo n.º 23
0
def violin_colorscale(
    data,
    data_header,
    group_header,
    colors,
    use_colorscale,
    group_stats,
    rugplot,
    sort,
    height,
    width,
    title,
):
    """
    Refer to FigureFactory.create_violin() for docstring.

    Returns fig for violin plot with colorscale.

    """

    # collect all group names
    group_name = []
    for name in data[group_header]:
        if name not in group_name:
            group_name.append(name)
    if sort:
        group_name.sort()

    # make sure all group names are keys in group_stats
    for group in group_name:
        if group not in group_stats:
            raise exceptions.PlotlyError("All values/groups in the index "
                                         "column must be represented "
                                         "as a key in group_stats.")

    gb = data.groupby([group_header])
    L = len(group_name)

    fig = make_subplots(rows=1,
                        cols=L,
                        shared_yaxes=True,
                        horizontal_spacing=0.025,
                        print_grid=False)

    # prepare low and high color for colorscale
    lowcolor = clrs.color_parser(colors[0], clrs.unlabel_rgb)
    highcolor = clrs.color_parser(colors[1], clrs.unlabel_rgb)

    # find min and max values in group_stats
    group_stats_values = []
    for key in group_stats:
        group_stats_values.append(group_stats[key])

    max_value = max(group_stats_values)
    min_value = min(group_stats_values)

    for k, gr in enumerate(group_name):
        vals = np.asarray(gb.get_group(gr)[data_header], np.float)

        # find intermediate color from colorscale
        intermed = (group_stats[gr] - min_value) / (max_value - min_value)
        intermed_color = clrs.find_intermediate_color(lowcolor, highcolor,
                                                      intermed)

        plot_data, plot_xrange = violinplot(
            vals, fillcolor="rgb{}".format(intermed_color), rugplot=rugplot)
        layout = graph_objs.Layout()

        for item in plot_data:
            fig.append_trace(item, 1, k + 1)
        fig["layout"].update(
            {"xaxis{}".format(k + 1): make_XAxis(group_name[k], plot_xrange)})
    # add colorbar to plot
    trace_dummy = graph_objs.Scatter(
        x=[0],
        y=[0],
        mode="markers",
        marker=dict(
            size=2,
            cmin=min_value,
            cmax=max_value,
            colorscale=[[0, colors[0]], [1, colors[1]]],
            showscale=True,
        ),
        showlegend=False,
    )
    fig.append_trace(trace_dummy, 1, L)

    # set the sharey axis style
    fig["layout"].update({"yaxis{}".format(1): make_YAxis("")})
    fig["layout"].update(
        title=title,
        showlegend=False,
        hovermode="closest",
        autosize=False,
        height=height,
        width=width,
    )

    return fig
Ejemplo n.º 24
0
def violin_dict(
    data,
    data_header,
    group_header,
    colors,
    use_colorscale,
    group_stats,
    rugplot,
    sort,
    height,
    width,
    title,
):
    """
    Refer to FigureFactory.create_violin() for docstring.

    Returns fig for violin plot without colorscale.

    """

    # collect all group names
    group_name = []
    for name in data[group_header]:
        if name not in group_name:
            group_name.append(name)

    if sort:
        group_name.sort()

    # check if all group names appear in colors dict
    for group in group_name:
        if group not in colors:
            raise exceptions.PlotlyError("If colors is a dictionary, all "
                                         "the group names must appear as "
                                         "keys in colors.")

    gb = data.groupby([group_header])
    L = len(group_name)

    fig = make_subplots(rows=1,
                        cols=L,
                        shared_yaxes=True,
                        horizontal_spacing=0.025,
                        print_grid=False)

    for k, gr in enumerate(group_name):
        vals = np.asarray(gb.get_group(gr)[data_header], np.float)
        plot_data, plot_xrange = violinplot(vals,
                                            fillcolor=colors[gr],
                                            rugplot=rugplot)
        layout = graph_objs.Layout()

        for item in plot_data:
            fig.append_trace(item, 1, k + 1)

        # add violin plot labels
        fig["layout"].update(
            {"xaxis{}".format(k + 1): make_XAxis(group_name[k], plot_xrange)})

    # set the sharey axis style
    fig["layout"].update({"yaxis{}".format(1): make_YAxis("")})
    fig["layout"].update(
        title=title,
        showlegend=False,
        hovermode="closest",
        autosize=False,
        height=height,
        width=width,
    )

    return fig
Ejemplo n.º 25
0
def create_dendrogram(
    X,
    orientation="bottom",
    labels=None,
    colorscale=None,
    distfun=None,
    linkagefun=lambda x: sch.linkage(x, "complete"),
    hovertext=None,
    color_threshold=None,
):
    """
    BETA function that returns a dendrogram Plotly figure object.

    :param (ndarray) X: Matrix of observations as array of arrays
    :param (str) orientation: 'top', 'right', 'bottom', or 'left'
    :param (list) labels: List of axis category labels(observation labels)
    :param (list) colorscale: Optional colorscale for dendrogram tree
    :param (function) distfun: Function to compute the pairwise distance from
                               the observations
    :param (function) linkagefun: Function to compute the linkage matrix from
                               the pairwise distances
    :param (list[list]) hovertext: List of hovertext for constituent traces of dendrogram
                               clusters
    :param (double) color_threshold: Value at which the separation of clusters will be made

    Example 1: Simple bottom oriented dendrogram

    >>> from plotly_study.figure_factory import create_dendrogram

    >>> import numpy as np

    >>> X = np.random.rand(10,10)
    >>> fig = create_dendrogram(X)
    >>> fig.show()

    Example 2: Dendrogram to put on the left of the heatmap
    
    >>> from plotly_study.figure_factory import create_dendrogram

    >>> import numpy as np

    >>> X = np.random.rand(5,5)
    >>> names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark']
    >>> dendro = create_dendrogram(X, orientation='right', labels=names)
    >>> dendro['layout'].update({'width':700, 'height':500})
    >>> dendro.show()

    Example 3: Dendrogram with Pandas
    
    >>> from plotly_study.figure_factory import create_dendrogram

    >>> import numpy as np
    >>> import pandas as pd

    >>> Index= ['A','B','C','D','E','F','G','H','I','J']
    >>> df = pd.DataFrame(abs(np.random.randn(10, 10)), index=Index)
    >>> fig = create_dendrogram(df, labels=Index)
    >>> fig.show()
    """
    if not scp or not scs or not sch:
        raise ImportError("FigureFactory.create_dendrogram requires scipy, \
                            scipy.spatial and scipy.hierarchy")

    s = X.shape
    if len(s) != 2:
        exceptions.PlotlyError("X should be 2-dimensional array.")

    if distfun is None:
        distfun = scs.distance.pdist

    dendrogram = _Dendrogram(
        X,
        orientation,
        labels,
        colorscale,
        distfun=distfun,
        linkagefun=linkagefun,
        hovertext=hovertext,
        color_threshold=color_threshold,
    )

    return graph_objs.Figure(data=dendrogram.data, layout=dendrogram.layout)
Ejemplo n.º 26
0
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

    Example 1: Simple Gantt Chart

    >>> from plotly_study.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_study.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_study.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_study.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_study.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
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
def trisurf(
    x,
    y,
    z,
    simplices,
    show_colorbar,
    edges_color,
    scale,
    colormap=None,
    color_func=None,
    plot_edges=False,
    x_edge=None,
    y_edge=None,
    z_edge=None,
    facecolor=None,
):
    """
    Refer to FigureFactory.create_trisurf() for docstring
    """
    # numpy import check
    if not np:
        raise ImportError("FigureFactory._trisurf() requires " "numpy imported.")
    points3D = np.vstack((x, y, z)).T
    simplices = np.atleast_2d(simplices)

    # vertices of the surface triangles
    tri_vertices = points3D[simplices]

    # Define colors for the triangle faces
    if color_func is None:
        # mean values of z-coordinates of triangle vertices
        mean_dists = tri_vertices[:, :, 2].mean(-1)
    elif isinstance(color_func, (list, np.ndarray)):
        # Pre-computed list / array of values to map onto color
        if len(color_func) != len(simplices):
            raise ValueError(
                "If color_func is a list/array, it must "
                "be the same length as simplices."
            )

        # convert all colors in color_func to rgb
        for index in range(len(color_func)):
            if isinstance(color_func[index], str):
                if "#" in color_func[index]:
                    foo = clrs.hex_to_rgb(color_func[index])
                    color_func[index] = clrs.label_rgb(foo)

            if isinstance(color_func[index], tuple):
                foo = clrs.convert_to_RGB_255(color_func[index])
                color_func[index] = clrs.label_rgb(foo)

        mean_dists = np.asarray(color_func)
    else:
        # apply user inputted function to calculate
        # custom coloring for triangle vertices
        mean_dists = []
        for triangle in tri_vertices:
            dists = []
            for vertex in triangle:
                dist = color_func(vertex[0], vertex[1], vertex[2])
                dists.append(dist)
            mean_dists.append(np.mean(dists))
        mean_dists = np.asarray(mean_dists)

    # Check if facecolors are already strings and can be skipped
    if isinstance(mean_dists[0], str):
        facecolor = mean_dists
    else:
        min_mean_dists = np.min(mean_dists)
        max_mean_dists = np.max(mean_dists)

        if facecolor is None:
            facecolor = []
        for index in range(len(mean_dists)):
            color = map_face2color(
                mean_dists[index], colormap, scale, min_mean_dists, max_mean_dists
            )
            facecolor.append(color)

    # Make sure facecolor is a list so output is consistent across Pythons
    facecolor = np.asarray(facecolor)
    ii, jj, kk = simplices.T

    triangles = graph_objs.Mesh3d(
        x=x, y=y, z=z, facecolor=facecolor, i=ii, j=jj, k=kk, name=""
    )

    mean_dists_are_numbers = not isinstance(mean_dists[0], str)

    if mean_dists_are_numbers and show_colorbar is True:
        # make a colorscale from the colors
        colorscale = clrs.make_colorscale(colormap, scale)
        colorscale = clrs.convert_colorscale_to_rgb(colorscale)

        colorbar = graph_objs.Scatter3d(
            x=x[:1],
            y=y[:1],
            z=z[:1],
            mode="markers",
            marker=dict(
                size=0.1,
                color=[min_mean_dists, max_mean_dists],
                colorscale=colorscale,
                showscale=True,
            ),
            hoverinfo="none",
            showlegend=False,
        )

    # the triangle sides are not plotted
    if plot_edges is False:
        if mean_dists_are_numbers and show_colorbar is True:
            return [triangles, colorbar]
        else:
            return [triangles]

    # define the lists x_edge, y_edge and z_edge, of x, y, resp z
    # coordinates of edge end points for each triangle
    # None separates data corresponding to two consecutive triangles
    is_none = [ii is None for ii in [x_edge, y_edge, z_edge]]
    if any(is_none):
        if not all(is_none):
            raise ValueError(
                "If any (x_edge, y_edge, z_edge) is None, " "all must be None"
            )
        else:
            x_edge = []
            y_edge = []
            z_edge = []

    # Pull indices we care about, then add a None column to separate tris
    ixs_triangles = [0, 1, 2, 0]
    pull_edges = tri_vertices[:, ixs_triangles, :]
    x_edge_pull = np.hstack(
        [pull_edges[:, :, 0], np.tile(None, [pull_edges.shape[0], 1])]
    )
    y_edge_pull = np.hstack(
        [pull_edges[:, :, 1], np.tile(None, [pull_edges.shape[0], 1])]
    )
    z_edge_pull = np.hstack(
        [pull_edges[:, :, 2], np.tile(None, [pull_edges.shape[0], 1])]
    )

    # Now unravel the edges into a 1-d vector for plotting
    x_edge = np.hstack([x_edge, x_edge_pull.reshape([1, -1])[0]])
    y_edge = np.hstack([y_edge, y_edge_pull.reshape([1, -1])[0]])
    z_edge = np.hstack([z_edge, z_edge_pull.reshape([1, -1])[0]])

    if not (len(x_edge) == len(y_edge) == len(z_edge)):
        raise exceptions.PlotlyError(
            "The lengths of x_edge, y_edge and " "z_edge are not the same."
        )

    # define the lines for plotting
    lines = graph_objs.Scatter3d(
        x=x_edge,
        y=y_edge,
        z=z_edge,
        mode="lines",
        line=graph_objs.scatter3d.Line(color=edges_color, width=1.5),
        showlegend=False,
    )

    if mean_dists_are_numbers and show_colorbar is True:
        return [triangles, lines, colorbar]
    else:
        return [triangles, lines]
Ejemplo n.º 29
0
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