Ejemplo n.º 1
0
    def map_array(self,
                  a: tp.ArrayLike,
                  idx_field: tp.Optional[str] = None,
                  value_map: tp.Optional[tp.ValueMapLike] = None,
                  group_by: tp.GroupByLike = None,
                  **kwargs) -> MappedArray:
        """Convert array to mapped array.

         The length of the array should match that of the records."""
        if not isinstance(a, np.ndarray):
            a = np.asarray(a)
        checks.assert_shape_equal(a, self.values)
        if idx_field is None:
            idx_field = self.idx_field
        if idx_field is not None:
            idx_arr = self.values[idx_field]
        else:
            idx_arr = None
        return MappedArray(self.wrapper,
                           a,
                           self.values['col'],
                           id_arr=self.values['id'],
                           idx_arr=idx_arr,
                           value_map=value_map,
                           **kwargs).regroup(group_by)
Ejemplo n.º 2
0
    def map_array(self, a, idx_arr=None, group_by=None, **kwargs):
        """Convert array to `MappedArray`.

         The length of the array should match that of the records."""
        if not isinstance(a, np.ndarray):
            a = np.asarray(a)
        checks.assert_shape_equal(a, self.records_arr)

        if idx_arr is None:
            if self.idx_field is not None:
                idx_arr = self.records_arr[self.idx_field]
            else:
                idx_arr = None
        if self.wrapper.grouper.is_grouping_changed(group_by=group_by):
            self.wrapper.grouper.check_group_by(group_by=group_by)
            wrapper = self.wrapper.copy(group_by=group_by)
        else:
            wrapper = self.wrapper
        return MappedArray(
            wrapper,
            a,
            self.records_arr['col'],
            idx_arr=idx_arr,
            **kwargs
        )
Ejemplo n.º 3
0
    def __init__(self, wrapper, mapped_arr, col_arr, idx_arr=None):
        Configured.__init__(
            self,
            wrapper=wrapper,
            mapped_arr=mapped_arr,
            col_arr=col_arr,
            idx_arr=idx_arr
        )
        checks.assert_type(wrapper, ArrayWrapper)
        if not isinstance(mapped_arr, np.ndarray):
            mapped_arr = np.asarray(mapped_arr)
        if not isinstance(col_arr, np.ndarray):
            col_arr = np.asarray(col_arr)
        checks.assert_shape_equal(mapped_arr, col_arr, axis=0)
        if idx_arr is not None:
            if not isinstance(idx_arr, np.ndarray):
                idx_arr = np.asarray(idx_arr)
            checks.assert_shape_equal(mapped_arr, idx_arr, axis=0)

        self._wrapper = wrapper
        self._mapped_arr = mapped_arr
        self._col_arr = col_arr
        self._idx_arr = idx_arr

        PandasIndexer.__init__(self, _mapped_array_indexing_func)
Ejemplo n.º 4
0
    def __init__(self,
                 wrapper: ArrayWrapper,
                 mapped_arr: tp.ArrayLike,
                 col_arr: tp.ArrayLike,
                 id_arr: tp.Optional[tp.ArrayLike] = None,
                 idx_arr: tp.Optional[tp.ArrayLike] = None,
                 mapping: tp.Optional[tp.MappingLike] = None,
                 col_mapper: tp.Optional[ColumnMapper] = None,
                 **kwargs) -> None:
        Wrapping.__init__(self,
                          wrapper,
                          mapped_arr=mapped_arr,
                          col_arr=col_arr,
                          id_arr=id_arr,
                          idx_arr=idx_arr,
                          mapping=mapping,
                          col_mapper=col_mapper,
                          **kwargs)
        StatsBuilderMixin.__init__(self)

        mapped_arr = np.asarray(mapped_arr)
        col_arr = np.asarray(col_arr)
        checks.assert_shape_equal(mapped_arr, col_arr, axis=0)
        if id_arr is None:
            id_arr = np.arange(len(mapped_arr))
        else:
            id_arr = np.asarray(id_arr)
        if idx_arr is not None:
            idx_arr = np.asarray(idx_arr)
            checks.assert_shape_equal(mapped_arr, idx_arr, axis=0)
        if mapping is not None:
            if isinstance(mapping, str):
                if mapping.lower() == 'index':
                    mapping = self.wrapper.index
                elif mapping.lower() == 'columns':
                    mapping = self.wrapper.columns
            mapping = to_mapping(mapping)

        self._mapped_arr = mapped_arr
        self._id_arr = id_arr
        self._col_arr = col_arr
        self._idx_arr = idx_arr
        self._mapping = mapping
        if col_mapper is None:
            col_mapper = ColumnMapper(wrapper, col_arr)
        self._col_mapper = col_mapper
Ejemplo n.º 5
0
    def wrap(self,
             a: tp.ArrayLike,
             index: tp.Optional[tp.IndexLike] = None,
             columns: tp.Optional[tp.IndexLike] = None,
             dtype: tp.Optional[tp.PandasDTypeLike] = None,
             group_by: tp.GroupByLike = None) -> tp.SeriesFrame:
        """Wrap a NumPy array using the stored metadata."""
        checks.assert_ndim(a, (1, 2))
        _self = self.resolve(group_by=group_by)

        if index is None:
            index = _self.index
        if not isinstance(index, pd.Index):
            index = pd.Index(index)
        if columns is None:
            columns = _self.columns
        if not isinstance(columns, pd.Index):
            columns = pd.Index(columns)
        if len(columns) == 1:
            name = columns[0]
            if name == 0:  # was a Series before
                name = None
        else:
            name = None

        arr = np.asarray(a)
        arr = reshape_fns.soft_to_ndim(arr, self.ndim)
        checks.assert_shape_equal(arr, index, axis=(0, 0))
        if arr.ndim == 2:
            checks.assert_shape_equal(arr, columns, axis=(1, 0))
        if arr.ndim == 1:
            return pd.Series(arr, index=index, name=name, dtype=dtype)
        if arr.ndim == 2:
            if arr.shape[1] == 1 and _self.ndim == 1:
                return pd.Series(arr[:, 0],
                                 index=index,
                                 name=name,
                                 dtype=dtype)
            return pd.DataFrame(arr, index=index, columns=columns, dtype=dtype)
        raise ValueError(f"{arr.ndim}-d input is not supported")
Ejemplo n.º 6
0
 def _wrap(arr):
     arr = np.asarray(arr)
     checks.assert_ndim(arr, (1, 2))
     if fillna is not None:
         arr[pd.isnull(arr)] = fillna
     arr = reshape_fns.soft_to_ndim(arr, self.ndim)
     checks.assert_shape_equal(arr, index, axis=(0, 0))
     if arr.ndim == 2:
         checks.assert_shape_equal(arr, columns, axis=(1, 0))
     if arr.ndim == 1:
         return pd.Series(arr, index=index, name=name, dtype=dtype)
     if arr.ndim == 2:
         if arr.shape[1] == 1 and _self.ndim == 1:
             return pd.Series(arr[:, 0],
                              index=index,
                              name=name,
                              dtype=dtype)
         return pd.DataFrame(arr,
                             index=index,
                             columns=columns,
                             dtype=dtype)
     raise ValueError(f"{arr.ndim}-d input is not supported")
Ejemplo n.º 7
0
    def map_array(self,
                  a: tp.ArrayLike,
                  idx_arr: tp.Optional[tp.ArrayLike] = None,
                  mapping: tp.Optional[tp.MappingLike] = None,
                  group_by: tp.GroupByLike = None,
                  **kwargs) -> MappedArray:
        """Convert array to mapped array.

         The length of the array should match that of the records."""
        if not isinstance(a, np.ndarray):
            a = np.asarray(a)
        checks.assert_shape_equal(a, self.values)
        if idx_arr is None:
            idx_arr = self.idx_arr
        return MappedArray(self.wrapper,
                           a,
                           self.col_arr,
                           id_arr=self.id_arr,
                           idx_arr=idx_arr,
                           mapping=mapping,
                           col_mapper=self.col_mapper,
                           **kwargs).regroup(group_by)
Ejemplo n.º 8
0
    def wrap(self,
             a,
             index=None,
             columns=None,
             dtype=None,
             collapse=None,
             **kwargs):
        """Wrap a NumPy array using the stored metadata."""
        checks.assert_ndim(a, (1, 2))
        group_by = self.grouper.resolve_group_by(**kwargs)

        a = np.asarray(a)
        a = reshape_fns.soft_to_ndim(a, self.ndim)
        if index is None:
            index = self.index
        if columns is None:
            columns = self.grouper.get_columns(**kwargs)
        if collapse is None:
            collapse = group_by is not None and group_by is not False and self.grouped_ndim == 1
        if columns is not None and len(columns) == 1:
            name = columns[0]
            if name == 0:  # was a Series before
                name = None
        else:
            name = None

        # Perform checks
        if index is not None:
            checks.assert_shape_equal(a, index, axis=(0, 0))
        if a.ndim == 2 and columns is not None:
            checks.assert_shape_equal(a, columns, axis=(1, 0))

        if a.ndim == 1:
            return pd.Series(a, index=index, name=name, dtype=dtype)
        if a.ndim == 2 and a.shape[1] == 1 and collapse:
            return pd.Series(a[:, 0], index=index, name=name, dtype=dtype)
        return pd.DataFrame(a, index=index, columns=columns, dtype=dtype)
Ejemplo n.º 9
0
    def __init__(self,
                 data: tp.Optional[tp.ArrayLike] = None,
                 x_labels: tp.Optional[tp.Labels] = None,
                 y_labels: tp.Optional[tp.Labels] = None,
                 z_labels: tp.Optional[tp.Labels] = None,
                 trace_kwargs: tp.KwargsLike = None,
                 add_trace_kwargs: tp.KwargsLike = None,
                 scene_name: str = 'scene',
                 fig: tp.Optional[tp.BaseFigure] = None,
                 **layout_kwargs) -> None:
        """Create a volume plot.

        Args:
            data (array_like): Data in any format that can be converted to NumPy.

                Must be a 3-dim array.
            x_labels (array_like): X-axis labels.
            y_labels (array_like): Y-axis labels.
            z_labels (array_like): Z-axis labels.
            trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Volume`.
            add_trace_kwargs (dict): Keyword arguments passed to `add_trace`.
            scene_name (str): Reference to the 3D scene.
            fig (Figure or FigureWidget): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.

        !!! note
            Figure widgets have currently problems displaying NaNs.
            Use `.show()` method for rendering.

        ## Example

        ```python-repl
        >>> import vectorbt as vbt
        >>> import numpy as np

        >>> volume = vbt.plotting.Volume(
        ...     data=np.random.randint(1, 10, size=(3, 3, 3)),
        ...     x_labels=['a', 'b', 'c'],
        ...     y_labels=['d', 'e', 'f'],
        ...     z_labels=['g', 'h', 'i']
        ... )
        >>> volume.fig
        ```

        ![](/docs/img/Volume.svg)
        """
        Configured.__init__(
            self,
            data=data,
            x_labels=x_labels,
            y_labels=y_labels,
            z_labels=z_labels,
            trace_kwargs=trace_kwargs,
            add_trace_kwargs=add_trace_kwargs,
            scene_name=scene_name,
            fig=fig,
            **layout_kwargs
        )

        from vectorbt._settings import settings
        layout_cfg = settings['plotting']['layout']

        if trace_kwargs is None:
            trace_kwargs = {}
        if add_trace_kwargs is None:
            add_trace_kwargs = {}
        if data is not None:
            checks.assert_ndim(data, 3)
            data = np.asarray(data)
            x_len, y_len, z_len = data.shape
            if x_labels is not None:
                checks.assert_shape_equal(data, x_labels, (0, 0))
            if y_labels is not None:
                checks.assert_shape_equal(data, y_labels, (1, 0))
            if z_labels is not None:
                checks.assert_shape_equal(data, z_labels, (2, 0))
        else:
            if x_labels is None or y_labels is None or z_labels is None:
                raise ValueError("At least data, or x_labels, y_labels and z_labels must be passed")
            x_len = len(x_labels)
            y_len = len(y_labels)
            z_len = len(z_labels)
        if x_labels is None:
            x_labels = np.arange(x_len)
        else:
            x_labels = clean_labels(x_labels)
        if y_labels is None:
            y_labels = np.arange(y_len)
        else:
            y_labels = clean_labels(y_labels)
        if z_labels is None:
            z_labels = np.arange(z_len)
        else:
            z_labels = clean_labels(z_labels)
        x_labels = np.asarray(x_labels)
        y_labels = np.asarray(y_labels)
        z_labels = np.asarray(z_labels)

        if fig is None:
            fig = make_figure()
            if 'width' in layout_cfg:
                # Calculate nice width and height
                fig.update_layout(
                    width=layout_cfg['width'],
                    height=0.7 * layout_cfg['width']
                )

        # Non-numeric data types are not supported by go.Volume, so use ticktext
        # Note: Currently plotly displays the entire tick array, in future versions it will be more sensible
        more_layout = dict()
        if not np.issubdtype(x_labels.dtype, np.number):
            x_ticktext = x_labels
            x_labels = np.arange(x_len)
            more_layout[scene_name] = dict(
                xaxis=dict(
                    ticktext=x_ticktext,
                    tickvals=x_labels,
                    tickmode='array'
                )
            )
        if not np.issubdtype(y_labels.dtype, np.number):
            y_ticktext = y_labels
            y_labels = np.arange(y_len)
            more_layout[scene_name] = dict(
                yaxis=dict(
                    ticktext=y_ticktext,
                    tickvals=y_labels,
                    tickmode='array'
                )
            )
        if not np.issubdtype(z_labels.dtype, np.number):
            z_ticktext = z_labels
            z_labels = np.arange(z_len)
            more_layout[scene_name] = dict(
                zaxis=dict(
                    ticktext=z_ticktext,
                    tickvals=z_labels,
                    tickmode='array'
                )
            )
        fig.update_layout(**more_layout)
        fig.update_layout(**layout_kwargs)

        # Arrays must have the same length as the flattened data array
        x = np.repeat(x_labels, len(y_labels) * len(z_labels))
        y = np.tile(np.repeat(y_labels, len(z_labels)), len(x_labels))
        z = np.tile(z_labels, len(x_labels) * len(y_labels))

        volume = go.Volume(
            x=x,
            y=y,
            z=z,
            opacity=0.2,
            surface_count=15,  # keep low for big data
            colorscale='Plasma'
        )
        volume.update(**trace_kwargs)
        fig.add_trace(volume, **add_trace_kwargs)

        TraceUpdater.__init__(self, fig, (fig.data[-1],))

        if data is not None:
            self.update(data)
Ejemplo n.º 10
0
    def __init__(self,
                 data: tp.Optional[tp.ArrayLike] = None,
                 x_labels: tp.Optional[tp.Labels] = None,
                 y_labels: tp.Optional[tp.Labels] = None,
                 is_x_category: bool = False,
                 is_y_category: bool = False,
                 trace_kwargs: tp.KwargsLike = None,
                 add_trace_kwargs: tp.KwargsLike = None,
                 fig: tp.Optional[tp.BaseFigure] = None,
                 **layout_kwargs) -> None:
        """Create a heatmap plot.

        Args:
            data (array_like): Data in any format that can be converted to NumPy.

                Must be of shape (`y_labels`, `x_labels`).
            x_labels (array_like): X-axis labels, corresponding to columns in pandas.
            y_labels (array_like): Y-axis labels, corresponding to index in pandas.
            is_x_category (bool): Whether X-axis is a categorical axis.
            is_y_category (bool): Whether Y-axis is a categorical axis.
            trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Heatmap`.
            add_trace_kwargs (dict): Keyword arguments passed to `add_trace`.
            fig (Figure or FigureWidget): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.

        ## Example

        ```python-repl
        >>> import vectorbt as vbt

        >>> heatmap = vbt.plotting.Heatmap(
        ...     data=[[1, 2], [3, 4]],
        ...     x_labels=['a', 'b'],
        ...     y_labels=['x', 'y']
        ... )
        >>> heatmap.fig
        ```
        ![](/docs/img/Heatmap.svg)
        """
        Configured.__init__(
            self,
            data=data,
            x_labels=x_labels,
            y_labels=y_labels,
            trace_kwargs=trace_kwargs,
            add_trace_kwargs=add_trace_kwargs,
            fig=fig,
            **layout_kwargs
        )

        from vectorbt._settings import settings
        layout_cfg = settings['plotting']['layout']

        if trace_kwargs is None:
            trace_kwargs = {}
        if add_trace_kwargs is None:
            add_trace_kwargs = {}
        if data is not None:
            data = reshape_fns.to_2d_array(data)
            if x_labels is not None:
                checks.assert_shape_equal(data, x_labels, (1, 0))
            if y_labels is not None:
                checks.assert_shape_equal(data, y_labels, (0, 0))
        else:
            if x_labels is None or y_labels is None:
                raise ValueError("At least data, or x_labels and y_labels must be passed")
        if x_labels is not None:
            x_labels = clean_labels(x_labels)
        if y_labels is not None:
            y_labels = clean_labels(y_labels)

        if fig is None:
            fig = make_figure()
            if 'width' in layout_cfg:
                # Calculate nice width and height
                max_width = layout_cfg['width']
                if data is not None:
                    x_len = data.shape[1]
                    y_len = data.shape[0]
                else:
                    x_len = len(x_labels)
                    y_len = len(y_labels)
                width = math.ceil(renormalize(
                    x_len / (x_len + y_len),
                    (0, 1),
                    (0.3 * max_width, max_width)
                ))
                width = min(width + 150, max_width)  # account for colorbar
                height = math.ceil(renormalize(
                    y_len / (x_len + y_len),
                    (0, 1),
                    (0.3 * max_width, max_width)
                ))
                height = min(height, max_width * 0.7)  # limit height
                fig.update_layout(
                    width=width,
                    height=height
                )

        heatmap = go.Heatmap(
            hoverongaps=False,
            colorscale='Plasma',
            x=x_labels,
            y=y_labels
        )
        heatmap.update(**trace_kwargs)
        fig.add_trace(heatmap, **add_trace_kwargs)

        axis_kwargs = dict()
        if is_x_category:
            if fig.data[-1]['xaxis'] is not None:
                axis_kwargs['xaxis' + fig.data[-1]['xaxis'][1:]] = dict(type='category')
            else:
                axis_kwargs['xaxis'] = dict(type='category')
        if is_y_category:
            if fig.data[-1]['yaxis'] is not None:
                axis_kwargs['yaxis' + fig.data[-1]['yaxis'][1:]] = dict(type='category')
            else:
                axis_kwargs['yaxis'] = dict(type='category')
        fig.update_layout(**axis_kwargs)
        fig.update_layout(**layout_kwargs)

        TraceUpdater.__init__(self, fig, (fig.data[-1],))

        if data is not None:
            self.update(data)
Ejemplo n.º 11
0
    def __init__(self,
                 data: tp.Optional[tp.ArrayLike] = None,
                 trace_names: tp.TraceNames = None,
                 horizontal: bool = False,
                 remove_nan: bool = True,
                 from_quantile: tp.Optional[float] = None,
                 to_quantile: tp.Optional[float] = None,
                 trace_kwargs: tp.KwargsLikeSequence = None,
                 add_trace_kwargs: tp.KwargsLike = None,
                 fig: tp.Optional[tp.BaseFigure] = None,
                 **layout_kwargs) -> None:
        """Create a box plot.

        For keyword arguments, see `Histogram`.

        ## Example

        ```python-repl
        >>> import vectorbt as vbt

        >>> box = vbt.plotting.Box(
        ...     data=[[1, 2], [3, 4], [2, 1]],
        ...     trace_names=['a', 'b']
        ... )
        >>> box.fig
        ```
        ![](/docs/img/Box.svg)
        """
        Configured.__init__(
            self,
            data=data,
            trace_names=trace_names,
            horizontal=horizontal,
            remove_nan=remove_nan,
            from_quantile=from_quantile,
            to_quantile=to_quantile,
            trace_kwargs=trace_kwargs,
            add_trace_kwargs=add_trace_kwargs,
            fig=fig,
            **layout_kwargs
        )

        if trace_kwargs is None:
            trace_kwargs = {}
        if add_trace_kwargs is None:
            add_trace_kwargs = {}
        if data is not None:
            data = reshape_fns.to_2d_array(data)
            if trace_names is not None:
                checks.assert_shape_equal(data, trace_names, (1, 0))
        else:
            if trace_names is None:
                raise ValueError("At least data or trace_names must be passed")
        if trace_names is None:
            trace_names = [None] * data.shape[1]
        if isinstance(trace_names, str):
            trace_names = [trace_names]

        if fig is None:
            fig = make_figure()
        fig.update_layout(**layout_kwargs)

        for i, trace_name in enumerate(trace_names):
            _trace_kwargs = resolve_dict(trace_kwargs, i=i)
            trace_name = _trace_kwargs.pop('name', trace_name)
            if trace_name is not None:
                trace_name = str(trace_name)
            box = go.Box(
                name=trace_name,
                showlegend=trace_name is not None
            )
            box.update(**_trace_kwargs)
            fig.add_trace(box, **add_trace_kwargs)

        TraceUpdater.__init__(self, fig, fig.data[-len(trace_names):])
        self._horizontal = horizontal
        self._remove_nan = remove_nan
        self._from_quantile = from_quantile
        self._to_quantile = to_quantile

        if data is not None:
            self.update(data)
Ejemplo n.º 12
0
    def __init__(self,
                 data: tp.Optional[tp.ArrayLike] = None,
                 trace_names: tp.TraceNames = None,
                 horizontal: bool = False,
                 remove_nan: bool = True,
                 from_quantile: tp.Optional[float] = None,
                 to_quantile: tp.Optional[float] = None,
                 trace_kwargs: tp.KwargsLikeSequence = None,
                 add_trace_kwargs: tp.KwargsLike = None,
                 fig: tp.Optional[tp.BaseFigure] = None,
                 **layout_kwargs) -> None:
        """Create a histogram plot.

        Args:
            data (array_like): Data in any format that can be converted to NumPy.

                Must be of shape (any, `trace_names`).
            trace_names (str or list of str): Trace names, corresponding to columns in pandas.
            horizontal (bool): Whether to plot horizontally.
            remove_nan (bool): Whether to remove NaN values.
            from_quantile (float): Filter out data points before this quantile.

                Should be in range `[0, 1]`.
            to_quantile (float): Filter out data points after this quantile.

                Should be in range `[0, 1]`.
            trace_kwargs (dict or list of dict): Keyword arguments passed to `plotly.graph_objects.Histogram`.

                Can be specified per trace as a sequence of dicts.
            add_trace_kwargs (dict): Keyword arguments passed to `add_trace`.
            fig (Figure or FigureWidget): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.

        ## Example

        ```python-repl
        >>> import vectorbt as vbt

        >>> hist = vbt.plotting.Histogram(
        ...     data=[[1, 2], [3, 4], [2, 1]],
        ...     trace_names=['a', 'b']
        ... )
        >>> hist.fig
        ```
        ![](/docs/img/Histogram.svg)
        """
        Configured.__init__(
            self,
            data=data,
            trace_names=trace_names,
            horizontal=horizontal,
            remove_nan=remove_nan,
            from_quantile=from_quantile,
            to_quantile=to_quantile,
            trace_kwargs=trace_kwargs,
            add_trace_kwargs=add_trace_kwargs,
            fig=fig,
            **layout_kwargs
        )

        if trace_kwargs is None:
            trace_kwargs = {}
        if add_trace_kwargs is None:
            add_trace_kwargs = {}
        if data is not None:
            data = reshape_fns.to_2d_array(data)
            if trace_names is not None:
                checks.assert_shape_equal(data, trace_names, (1, 0))
        else:
            if trace_names is None:
                raise ValueError("At least data or trace_names must be passed")
        if trace_names is None:
            trace_names = [None] * data.shape[1]
        if isinstance(trace_names, str):
            trace_names = [trace_names]

        if fig is None:
            fig = make_figure()
            fig.update_layout(barmode='overlay')
        fig.update_layout(**layout_kwargs)

        for i, trace_name in enumerate(trace_names):
            _trace_kwargs = resolve_dict(trace_kwargs, i=i)
            trace_name = _trace_kwargs.pop('name', trace_name)
            if trace_name is not None:
                trace_name = str(trace_name)
            hist = go.Histogram(
                opacity=0.75 if len(trace_names) > 1 else 1,
                name=trace_name,
                showlegend=trace_name is not None
            )
            hist.update(**_trace_kwargs)
            fig.add_trace(hist, **add_trace_kwargs)

        TraceUpdater.__init__(self, fig, fig.data[-len(trace_names):])
        self._horizontal = horizontal
        self._remove_nan = remove_nan
        self._from_quantile = from_quantile
        self._to_quantile = to_quantile

        if data is not None:
            self.update(data)
Ejemplo n.º 13
0
    def __init__(self,
                 data: tp.Optional[tp.ArrayLike] = None,
                 trace_names: tp.TraceNames = None,
                 x_labels: tp.Optional[tp.Labels] = None,
                 trace_kwargs: tp.KwargsLikeSequence = None,
                 add_trace_kwargs: tp.KwargsLike = None,
                 fig: tp.Optional[tp.BaseFigure] = None,
                 **layout_kwargs) -> None:
        """Create a scatter plot.

        Args:
            data (array_like): Data in any format that can be converted to NumPy.

                Must be of shape (`x_labels`, `trace_names`).
            trace_names (str or list of str): Trace names, corresponding to columns in pandas.
            x_labels (array_like): X-axis labels, corresponding to index in pandas.
            trace_kwargs (dict or list of dict): Keyword arguments passed to `plotly.graph_objects.Scatter`.

                Can be specified per trace as a sequence of dicts.
            add_trace_kwargs (dict): Keyword arguments passed to `add_trace`.
            fig (Figure or FigureWidget): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.

        ## Example

        ```python-repl
        >>> import vectorbt as vbt

        >>> scatter = vbt.plotting.Scatter(
        ...     data=[[1, 2], [3, 4]],
        ...     trace_names=['a', 'b'],
        ...     x_labels=['x', 'y']
        ... )
        >>> scatter.fig
        ```
        ![](/docs/img/Scatter.svg)
        """
        Configured.__init__(
            self,
            data=data,
            trace_names=trace_names,
            x_labels=x_labels,
            trace_kwargs=trace_kwargs,
            add_trace_kwargs=add_trace_kwargs,
            fig=fig,
            **layout_kwargs
        )

        if trace_kwargs is None:
            trace_kwargs = {}
        if add_trace_kwargs is None:
            add_trace_kwargs = {}
        if data is not None:
            data = reshape_fns.to_2d_array(data)
            if trace_names is not None:
                checks.assert_shape_equal(data, trace_names, (1, 0))
        else:
            if trace_names is None:
                raise ValueError("At least data or trace_names must be passed")
        if trace_names is None:
            trace_names = [None] * data.shape[1]
        if isinstance(trace_names, str):
            trace_names = [trace_names]
        if x_labels is not None:
            x_labels = clean_labels(x_labels)

        if fig is None:
            fig = make_figure()
        fig.update_layout(**layout_kwargs)

        for i, trace_name in enumerate(trace_names):
            _trace_kwargs = resolve_dict(trace_kwargs, i=i)
            trace_name = _trace_kwargs.pop('name', trace_name)
            if trace_name is not None:
                trace_name = str(trace_name)
            scatter = go.Scatter(
                x=x_labels,
                name=trace_name,
                showlegend=trace_name is not None
            )
            scatter.update(**_trace_kwargs)
            fig.add_trace(scatter, **add_trace_kwargs)

        TraceUpdater.__init__(self, fig, fig.data[-len(trace_names):])

        if data is not None:
            self.update(data)
Ejemplo n.º 14
0
 def test_assert_shape_equal(self):
     checks.assert_shape_equal(0, 1)
     checks.assert_shape_equal([1, 2, 3], np.asarray([1, 2, 3]))
     checks.assert_shape_equal([1, 2, 3], pd.Series([1, 2, 3]))
     checks.assert_shape_equal(np.zeros((3, 3)), pd.Series([1, 2, 3]), axis=0)
     checks.assert_shape_equal(np.zeros((2, 3)), pd.Series([1, 2, 3]), axis=(1, 0))
     with pytest.raises(Exception) as e_info:
         checks.assert_shape_equal(np.zeros((2, 3)), pd.Series([1, 2, 3]), axis=(0, 1))