Skip to content

Commit

Permalink
Merge db7012d into 17ce0cc
Browse files Browse the repository at this point in the history
  • Loading branch information
ppwadhwa committed Nov 17, 2021
2 parents 17ce0cc + db7012d commit 328d4fd
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 18 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
exclude:
- os: windows-latest
python-version: 2.7
timeout-minutes: 30
timeout-minutes: 60
defaults:
run:
shell: bash -l {0}
Expand Down Expand Up @@ -57,6 +57,12 @@ jobs:
conda activate test-environment
conda list
doit develop_install -c pyviz/label/dev -o tests
- name: Handling the decorator package on ubuntu and python 2.7
if: matrix.os == 'ubuntu-latest' && startsWith(matrix.python-version, 2.)
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
conda install -c pyviz/label/dev 'decorator=4.4.2'
- name: doit develop_install py3
if: startsWith(matrix.python-version, 3.)
run: |
Expand Down
45 changes: 32 additions & 13 deletions examples/user_guide/Pandas_API.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -537,9 +537,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"plot_1 = df.plot.scatter(x='a', y='b', color='DarkBlue', label='Group 1')\n",
Expand Down Expand Up @@ -683,7 +681,16 @@
"\n",
"### Scatter Matrix Plot\n",
"\n",
"You can create a scatter plot matrix using the `scatter_matrix` method in `hvplot.plotting`:"
"You can create a scatter plot matrix using the `scatter_matrix` function:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd, numpy as np"
]
},
{
Expand All @@ -699,6 +706,24 @@
"scatter_matrix(df, alpha=0.2, diagonal='kde')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since scatter matrix plots may generate a large number of points (the one above renders 120,000 points!), you man want to take advantage of the power provided by [Datashader](https://datashader.org/) to rasterize the off-diagonal plots:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.DataFrame(np.random.randn(10000, 4), columns=['a', 'b', 'c', 'd'])\n",
"\n",
"scatter_matrix(df, datashade=True, dynspread=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -1013,9 +1038,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"(mean_std.plot.bar(y='mean', alpha=0.7) * \\\n",
Expand Down Expand Up @@ -1058,9 +1081,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"# Doesn't currently work as expected. Work-around:\n",
Expand Down Expand Up @@ -1102,9 +1123,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"from bokeh.sampledata import iris\n",
Expand Down
106 changes: 103 additions & 3 deletions hvplot/plotting/scatter_matrix.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from __future__ import absolute_import
from functools import partial
import warnings

import holoviews as _hv

Expand All @@ -11,6 +13,7 @@ def scatter_matrix(data, c=None, chart='scatter', diagonal='hist',
alpha=0.5, nonselection_alpha=0.1,
tools=None, cmap=None, colormap=None,
diagonal_kwds=None, hist_kwds=None, density_kwds=None,
datashade=False, rasterize=False, dynspread=False, spread=False,
**kwds):
"""
Scatter matrix of numeric columns.
Expand Down Expand Up @@ -43,7 +46,22 @@ def scatter_matrix(data, c=None, chart='scatter', diagonal='hist',
Default is `Category10 <https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md#category10>`.
diagonal_kwds/hist_kwds/density_kwds: dict, optional
Keyword options for the diagonal plots
kwds: Keyword options for the off-diagonal plots, optional
datashade (default=False):
Whether to apply rasterization and shading using datashader
library returning an RGB object
rasterize (default=False):
Whether to apply rasterization using the datashader library
returning an aggregated Image
dynspread (default=False):
Allows plots generated with datashade=True or rasterize=True
to increase the point size to make sparse regions more visible.
kwds supported include ``max_px``, ``threshold``, ``shape``, ``how`` and ``mask``.
spread (default=False):
Allows plots generated with datashade=True or rasterize=True
to increase the point size to make sparse regions more visible, by
applying a fixed spreading of a certain number of cells/pixels. kwds
supported include: ``px``, ``shape``, ``how`` and ``mask``.
kwds: Keyword options for the off-diagonal plots and datashader's spreading , optional
Returns:
--------
Expand All @@ -54,6 +72,7 @@ def scatter_matrix(data, c=None, chart='scatter', diagonal='hist',
--------
:func:`pandas.plotting.scatter_matrix` : Equivalent pandas function.
"""

data = _hv.Dataset(data)
supported = list(HoloViewsConverter._kind_mapping)
if diagonal not in supported:
Expand All @@ -65,20 +84,88 @@ def scatter_matrix(data, c=None, chart='scatter', diagonal='hist',
diagonal = HoloViewsConverter._kind_mapping[diagonal]
chart = HoloViewsConverter._kind_mapping[chart]

if rasterize or datashade:
try:
import datashader # noqa
except ImportError:
raise ImportError("rasterize or datashade require "
"datashader to be installed.")
from ..util import hv_version
if hv_version <= '1.14.6':
warnings.warn(
"Versions of holoviews before 1.14.7 did not suppport "
"dynamic update of rasterized/datashaded scatter matrix. "
"Update holoviews to a newer version."
)

if rasterize and datashade:
raise ValueError("Choose to either rasterize or "
"datashade the scatter matrix.")

if not rasterize and not datashade and (spread or dynspread):
raise ValueError("dynspread or spread need rasterize "
"or datashade to be set to True.")

if rasterize:
import holoviews.operation.datashader as hd
if dynspread or spread:
if hd.ds_version < '0.12.0':
raise RuntimeError(
'Any version of datashader less than 0.12.0 does '
'not support rasterize with dynspread or spread.')

#remove datashade kwds
if datashade or rasterize:
import holoviews.operation.datashader as hd

ds_kwds = {}
if 'aggregator' in kwds:
ds_kwds['aggregator'] = kwds.pop('aggregator')

#remove dynspread kwds
sp_kwds = {}
if dynspread:
if 'max_px' in kwds:
sp_kwds['max_px'] = kwds.pop('max_px')
if 'threshold' in kwds:
sp_kwds['threshold'] = kwds.pop('threshold')
if 'shape' in kwds:
sp_kwds['shape'] = kwds.pop('shape')
if 'how' in kwds:
sp_kwds['how'] = kwds.pop('how')
if 'mask' in kwds:
sp_kwds['mask'] = kwds.pop('mask')
if spread:
if 'px' in kwds:
sp_kwds['px'] = kwds.pop('px')
if 'shape' in kwds:
sp_kwds['shape'] = kwds.pop('shape')
if 'how' in kwds:
sp_kwds['how'] = kwds.pop('how')
if 'mask' in kwds:
sp_kwds['mask'] = kwds.pop('mask')

if cmap and colormap:
raise TypeError("Only specify one of `cmap` and `colormap`.")
colors = cmap or colormap or _hv.plotting.util.process_cmap('Category10', categorical=True)
tools = tools or ['box_select', 'lasso_select']
chart_opts = dict(alpha=alpha, cmap=colors, tools=tools,
nonselection_alpha=nonselection_alpha, **kwds)

#get initial scatter matrix. No color.
grid = _hv.operation.gridmatrix(data, diagonal_type=diagonal, chart_type=chart)

if c:
chart_opts['color_index'] = c
#change colors for scatter matrix
chart_opts['color'] = c
# Add color vdim to each plot.
grid = grid.map(lambda x: x.clone(vdims=x.vdims+[c]), 'Scatter')
# create a new scatter matrix with groups for each catetory, so now the histogram will
# show separate colors for each group.
groups = _hv.operation.gridmatrix(data.groupby(c).overlay(),
chart_type=chart,
diagonal_type=diagonal)
# take the correct layer from each Overlay object within the scatter matrix.
grid = (grid * groups).map(lambda x: x.get(0) if isinstance(x.get(0), chart) else x.get(1),
_hv.Overlay)

Expand All @@ -89,5 +176,18 @@ def scatter_matrix(data, c=None, chart='scatter', diagonal='hist',
'`density_kwds`.')

diagonal_kwds = diagonal_kwds or hist_kwds or density_kwds or {}
# set the histogram colors
diagonal_opts = dict(fill_color=_hv.Cycle(values=colors), **diagonal_kwds)
return grid.options({chart.__name__: chart_opts, diagonal.__name__: diagonal_opts})
# actually changing to the same color scheme for both scatter and histogram plots.
grid = grid.options({chart.__name__: chart_opts, diagonal.__name__: diagonal_opts})

# Perform datashade options after all the coloring is finished.
if datashade or rasterize:
aggregatefn = hd.datashade if datashade else hd.rasterize
grid = grid.map(partial(aggregatefn, **ds_kwds), specs=chart)
if spread or dynspread:
spreadfn = hd.dynspread if dynspread else (hd.spread if spread else lambda z, **_: z)
eltype = _hv.RGB if datashade else _hv.Image
grid = grid.map(partial(spreadfn, **sp_kwds), specs=eltype)

return grid
Empty file.

0 comments on commit 328d4fd

Please sign in to comment.