Exemplo n.º 1
0
def retrieve_chart_data(df, *args, **kwargs):
    """
    Retrieves data from a dataframe for x, y, z & group inputs complete with date frequency
    formatting (:meth:`dtale.charts.utils.date_freq_handler`) if specified

    :param df: dataframe that contains data for chart
    :type df: :class:`pandas:pandas.DataFrame`
    :param args: columns to use
    :type args: iterable of str
    :return: dataframe of data required for chart construction
    :rtype: :class:`pandas:pandas.DataFrame`
    """
    freq_handler = date_freq_handler(df)
    cols = flatten_lists([make_list(a) for a in args])
    all_code = []
    all_data = []
    for col in cols:
        if col is not None:
            s, code = freq_handler(col)
            all_data.append(s)
            if code is not None:
                all_code.append(code)
    all_data = pd.concat(all_data, axis=1)
    all_code = ["chart_data = pd.concat(["] + all_code + ["], axis=1)"]
    if len(make_list(kwargs.get("group_val"))):
        filters = build_group_inputs_filter(all_data, kwargs["group_val"])
        all_data = run_query(all_data, filters)
        all_code.append("chart_data = chart_data.query({})".format(
            triple_quote(filters)))
    return all_data, all_code
Exemplo n.º 2
0
def retrieve_chart_data(df, *args, **kwargs):
    """
    Retrieves data from a dataframe for x, y, z & group inputs complete with date frequency
    formatting (:meth:`dtale.charts.utils.date_freq_handler`) if specified

    :param df: dataframe that contains data for chart
    :type df: :class:`pandas:pandas.DataFrame`
    :param args: columns to use
    :type args: iterable of str
    :return: dataframe of data required for chart construction
    :rtype: :class:`pandas:pandas.DataFrame`
    """
    freq_handler = date_freq_handler(df)
    cols = flatten_lists([make_list(a) for a in args])
    all_code = []
    all_data = []
    for col in cols:
        if col is not None:
            s, code = freq_handler(col)
            all_data.append(s)
            if code is not None:
                all_code.append(code)
    all_data = pd.concat(all_data, axis=1)
    all_code = ["chart_data = pd.concat(["] + all_code + ["], axis=1)"]
    if len(make_list(kwargs.get('group_val'))):
        dtypes = get_dtypes(all_data)

        def _group_filter(group_val):
            for gc, gv in group_val.items():
                classifier = classify_type(dtypes[gc])
                yield group_filter_handler(gc, gv, classifier)

        def _full_filter():
            for group_val in kwargs['group_val']:
                group_filter = ' and '.join(list(_group_filter(group_val)))
                yield group_filter

        filters = list(_full_filter())
        filters = '({})'.format(') or ('.join(filters))
        all_data = all_data.query(filters)
        all_code.append('chart_data = chart_data.query({})'.format(filters))
    return all_data, all_code
Exemplo n.º 3
0
def build_layout():
    return flatten_lists([[
        dcc.Store(id="saved-chart-config-{}".format(i)),
        dcc.Store(id="prev-saved-chart-config-{}".format(i)),
        dcc.Store(id="saved-deletes-{}".format(i), data=0),
        html.Div(
            [
                html.Div(
                    [
                        html.H3(
                            "{} {}".format(text("Saved Chart"), i),
                            className="col-auto pr-3",
                        ),
                        html.Div(
                            id="saved-chart-header-{}".format(i),
                            className="col pl-0",
                        ),
                        html.Div(
                            dbc.Button(
                                text("Delete"),
                                id="delete-saved-btn-{}".format(i),
                                color="primary",
                                className="delete-chart",
                            ),
                            className="col-auto",
                        ),
                    ],
                    className="row",
                ),
                html.Div(id="saved-chart-{}".format(i)),
            ],
            id="saved-chart-div-{}".format(i),
            className="saved-chart-div pt-5",
            style=dict(display="none"),
        ),
    ] for i in SAVED_CHART_IDS])
Exemplo n.º 4
0
def build_selections(*args):
    """
    simple helper function to build a single level list of values based on variable number of inputs which could be
    equal to None.
    """
    return flatten_lists([[] if a is None else make_list(a) for a in args])
Exemplo n.º 5
0
def build_chart(data_id=None, **inputs):
    """
    Factory method that forks off into the different chart building methods (heatmaps are handled separately)
        - line
        - bar
        - scatter
        - pie
        - wordcloud
        - 3D scatter
        - surface

    :param data_id: identifier of data to build axis configurations against
    :type data_id: str
    :param inputs: Optional keyword arguments containing the following information:
        - x: column to be used as x-axis of chart
        - y: column to be used as y-axis of chart
        - z: column to use for the Z-Axis
        - agg: points to a specific function that can be applied to :func: pandas.core.groupby.DataFrameGroupBy
    :return: plotly chart object(s)
    :rtype: type of (:dash:`dash_core_components.Graph <dash-core-components/graph>`, dict)
    """
    try:
        if inputs.get('chart_type') == 'heatmap':
            data = make_timeout_request(threaded_heatmap_builder,
                                        kwargs=dict_merge(
                                            dict(data_id=data_id), inputs))
            data = data.pop()
            return data, None

        data = make_timeout_request(threaded_build_figure_data,
                                    kwargs=dict_merge(dict(data_id=data_id),
                                                      inputs))
        data = data.pop()
        if data is None:
            return None, None

        if 'error' in data:
            return build_error(data['error'], data['traceback']), None

        range_data = dict(min=data['min'], max=data['max'])
        axis_inputs = inputs.get('yaxis', {})
        chart_builder = chart_wrapper(data_id, data, inputs)
        chart_type, x, y, z, agg = (
            inputs.get(p) for p in ['chart_type', 'x', 'y', 'z', 'agg'])
        z = z if chart_type in ZAXIS_CHARTS else None
        chart_inputs = {
            k: v
            for k, v in inputs.items()
            if k not in ['chart_type', 'x', 'y', 'z', 'group']
        }

        if chart_type == 'wordcloud':
            return (chart_builder(
                dash_components.Wordcloud(id='wc',
                                          data=data,
                                          y=y,
                                          group=inputs.get('group'))),
                    range_data)

        axes_builder = build_axes(data_id,
                                  x,
                                  axis_inputs,
                                  data['min'],
                                  data['max'],
                                  z=z,
                                  agg=agg)
        if chart_type == 'scatter':
            if inputs['cpg']:
                scatter_charts = flatten_lists([
                    scatter_builder(data,
                                    x,
                                    y,
                                    axes_builder,
                                    chart_builder,
                                    group=group,
                                    agg=agg) for group in data['data']
                ])
            else:
                scatter_charts = scatter_builder(data,
                                                 x,
                                                 y,
                                                 axes_builder,
                                                 chart_builder,
                                                 agg=agg)
            return cpg_chunker(scatter_charts), range_data

        if chart_type == '3d_scatter':
            return scatter_builder(data,
                                   x,
                                   y,
                                   axes_builder,
                                   chart_builder,
                                   z=z,
                                   agg=agg), range_data

        if chart_type == 'surface':
            return surface_builder(data,
                                   x,
                                   y,
                                   z,
                                   axes_builder,
                                   chart_builder,
                                   agg=agg), range_data

        if chart_type == 'bar':
            return bar_builder(data, x, y, axes_builder, chart_builder,
                               **chart_inputs), range_data

        if chart_type == 'line':
            return line_builder(data, x, y, axes_builder, chart_builder,
                                **chart_inputs), range_data

        if chart_type == 'pie':
            return pie_builder(data, x, y, chart_builder,
                               **chart_inputs), range_data
        raise NotImplementedError('chart type: {}'.format(chart_type))
    except BaseException as e:
        return build_error(str(e), str(traceback.format_exc())), None
Exemplo n.º 6
0
def line_builder(data, x, y, axes_builder, wrapper, cpg=False, **inputs):
    """
    Builder function for :plotly:`plotly.graph_objects.Scatter(mode='lines') <plotly.graph_objects.Scatter>`

    :param data: raw data to be represented within line chart
    :type data: dict
    :param x: column to use for the X-Axis
    :type x: str
    :param y: columns to use for the Y-Axes
    :type y: list of str
    :param axes_builder: function for building axis configurations
    :type axes_builder: func
    :param wrapper: wrapper function returned by :meth:`dtale.charts.utils.chart_wrapper`
    :type wrapper: func
    :param cpg: `True` if charts are split by groups, `False` if all are contained within one chart
    :type cpg: bool
    :param inputs: Optional keyword arguments containing information about which aggregation (if any) has been used
    :type inputs: dict
    :return: line chart
    :rtype: :plotly:`plotly.graph_objects.Scatter(mode='lines') <plotly.graph_objects.Scatter>`
    """

    axes = axes_builder(y)
    name_builder = build_series_name(y, cpg)
    line_cfg = {'mode': 'lines', 'line': {'shape': 'spline', 'smoothing': 0.3}}
    if cpg:
        charts = [
            wrapper(
                dcc.Graph(
                    id='line-{}-graph'.format(series_key),
                    figure={
                        'data': [
                            go.Scatter(
                                **dict_merge(line_cfg, {
                                    'x': series['x'],
                                    'y': series[y2]
                                }, name_builder(y2, series_key), {} if i == 1
                                             else {'yaxis': 'y{}'.format(i)}))
                            for i, y2 in enumerate(y, 1)
                        ],
                        'layout':
                        build_layout(
                            dict_merge(
                                build_title(x,
                                            y,
                                            group=series_key,
                                            agg=inputs.get('agg')), axes))
                    })) for series_key, series in data['data'].items()
        ]
        return cpg_chunker(charts)

    data_cfgs = flatten_lists([[
        go.Scatter(**dict_merge(line_cfg, {
            'x': series['x'],
            'y': series[y2]
        }, name_builder(y2, series_key), {} if i ==
                                1 else {'yaxis': 'y{}'.format(i)}))
        for i, y2 in enumerate(y, 1)
    ] for series_key, series in data['data'].items()])
    return wrapper(
        dcc.Graph(id='line-graph',
                  figure={
                      'data':
                      data_cfgs,
                      'layout':
                      build_layout(
                          dict_merge(build_title(x, y, agg=inputs.get('agg')),
                                     axes))
                  }))
Exemplo n.º 7
0
def bar_builder(data,
                x,
                y,
                axes_builder,
                wrapper,
                cpg=False,
                barmode='group',
                barsort=None,
                **kwargs):
    """
    Builder function for :plotly:`plotly.graph_objects.Surface <plotly.graph_objects.Surface>`

    :param data: raw data to be represented within surface chart
    :type data: dict
    :param x: column to use for the X-Axis
    :type x: str
    :param y: columns to use for the Y-Axes
    :type y: list of str
    :param axes_builder: function for building axis configurations
    :type axes_builder: func
    :param wrapper: wrapper function returned by :meth:`dtale.charts.utils.chart_wrapper`
    :type wrapper: func
    :param group: column(s) to use for grouping
    :type group: list of str or str
    :param agg: points to a specific function that can be applied to
                :func: pandas.core.groupby.DataFrameGroupBy.  Possible values are: count, first, last mean,
                median, min, max, std, var, mad, prod, sum
    :type agg: str
    :return: surface chart
    :rtype: :plotly:`plotly.graph_objects.Surface <plotly.graph_objects.Surface>`
    """
    hover_text = dict()
    multiaxis = barmode is None or barmode == 'group'
    axes = axes_builder(y) if multiaxis else axes_builder([y[0]])
    name_builder = build_series_name(y, cpg)
    if barsort is not None:
        for series_key, series in data['data'].items():
            barsort_col = 'x' if barsort == x or barsort not in series else barsort
            if barsort_col != 'x':
                df = pd.DataFrame(series)
                df = df.sort_values(barsort_col)
                data['data'][series_key] = {
                    c: df[c].values
                    for c in df.columns
                }
                data['data'][series_key]['x'] = list(range(len(df['x'])))
                hover_text[series_key] = {
                    'hovertext': df['x'].values,
                    'hoverinfo': 'y+text'
                }
                axes['xaxis'] = dict_merge(axes.get('xaxis', {}),
                                           build_spaced_ticks(df['x'].values))

    if cpg:
        charts = [
            wrapper(
                dcc.Graph(id='bar-{}-graph'.format(series_key),
                          figure={
                              'data': [
                                  dict_merge(
                                      {
                                          'x': series['x'],
                                          'y': series[y2],
                                          'type': 'bar'
                                      }, name_builder(y2, series_key),
                                      {} if i == 1 or not multiaxis else
                                      {'yaxis': 'y{}'.format(i)},
                                      hover_text.get(series_key) or {})
                                  for i, y2 in enumerate(y, 1)
                              ],
                              'layout':
                              build_layout(
                                  dict_merge(
                                      build_title(x,
                                                  y,
                                                  series_key,
                                                  agg=kwargs.get('agg')), axes,
                                      dict(barmode=barmode or 'group')))
                          })) for series_key, series in data['data'].items()
        ]
        return cpg_chunker(charts)

    data_cfgs = flatten_lists([[
        dict_merge(
            {
                'x': series['x'],
                'y': series[y2],
                'type': 'bar'
            }, name_builder(y2, series_key),
            {} if i == 1 or not multiaxis else {'yaxis': 'y{}'.format(i)},
            hover_text.get(series_key) or {}) for i, y2 in enumerate(y, 1)
    ] for series_key, series in data['data'].items()])
    if barmode == 'group' and len(y or []) > 1:
        data_cfgs = list(build_grouped_bars_with_multi_yaxis(data_cfgs, y))

    return wrapper(
        dcc.Graph(id='bar-graph',
                  figure={
                      'data':
                      data_cfgs,
                      'layout':
                      build_layout(
                          dict_merge(build_title(x, y, agg=kwargs.get('agg')),
                                     axes, dict(barmode=barmode or 'group')))
                  }))
Exemplo n.º 8
0
 def build_selections(*args):
     return flatten_lists([[] if a is None else make_list(a) for a in args])