Scatter


D3Blocks.scatter(x, y, x1=None, y1=None, x2=None, y2=None, x3=None, y3=None, jitter=None, size=3, color='#002147', c_gradient='opaque', opacity=0.6, stroke='#ffffff', tooltip=None, cmap='tab20', scale=False, color_background='#ffffff', label_radio=['(x, y)', '(x1, y1)', '(x2, y2)', '(x3, y3)'], xlim=[None, None], ylim=[None, None], title='Scatter - D3blocks', filepath='scatter.html', figsize=[1024, 768], showfig=True, overwrite=True, notebook=False, save_button: bool = True, return_html: bool = False, reset_properties=True)

Scatterplot block.

The scatter plot is perhaps the most well-known chart to plot x, and y coordinates. Basic charts are very useful from time to time, especially with the brushing and zooming capabilities. The scatter plots can be sample-wise colored and used to detect relationships between (groups of) variables. The input data frame should contain 2 columns (x and y) with the coordinates, and the index represents the class label.

Parameters:
  • x (numpy array) – 1d coordinates x-axis.

  • y (numpy array) – 1d coordinates y-axis.

  • x1 (numpy array) – Second set of 1d coordinates x-axis.

  • y1 (numpy array) – Second set of 1d coordinates y-axis.

  • x2 (numpy array) – Third set of 1d coordinates x-axis.

  • y2 (numpy array) – Third set of 1d coordinates y-axis.

  • x3 (numpy array) – Fourth set of 1d coordinates x-axis.

  • y3 (numpy array) – Fourth set of 1d coordinates y-axis.

  • jitter (float, default: None) – Add jitter to data points as random normal data. Values of 0.01 is usually good for one-hot data seperation.

  • size (list/array of with same size as (x,y).) – Size of the samples.

  • color (list/array of hex colors with same size as (x,y)) –

    • ‘#ffffff’ : All dots are get the same hex color.

    • None: The same color as for c is applied.

    • [‘#000000’, ‘#ffffff’,…]: list/array of hex colors with same size as (x,y)

  • stroke (list/array of hex colors with same size as (x,y)) –

    Edgecolor of dotsize in hex colors.
    • ’#000000’ : All dots are get the same hex color.

    • [‘#000000’, ‘#ffffff’,…]: list/array of hex colors with same size as (x,y)

  • c_gradient (String, (default: 'opaque')) –

    Hex color to make a lineair gradient using the density.
    • None: Do not use gradient.

    • opaque: Towards the edges the points become more transparant. This will stress the dense areas and make scatter plot tidy.

    • ’#FFFFFF’: Towards the edges it smooths into this color

  • opacity (float or list/array [0-1]) – Opacity of the dot. Shoud be same size as (x,y)

  • tooltip (list of labels with same size as (x,y)) – labels of the samples.

  • cmap (String, (default: 'inferno')) –

    All colors can be reversed with ‘_r’, e.g. ‘binary’ to ‘binary_r’
    • ’tab20c’, ‘Set1’, ‘Set2’, ‘rainbow’, ‘bwr’, ‘binary’, ‘seismic’, ‘Blues’, ‘Reds’, ‘Pastel1’, ‘Paired’, ‘twilight’, ‘hsv’

  • scale (Bool, optional) – Scale datapoints. The default is False.

  • label_radio (List ['(x, y)', '(x1, y1)', '(x2, y2)', '(x3, y3)']) – The labels used for the radiobuttons.

  • set_xlim (tuple, (default: [None, None])) – Width of the x-axis: The default is extracted from the data with 10% spacing.

  • set_ylim (tuple, (default: [None, None])) – Height of the y-axis: The default is extracted from the data with 10% spacing.

  • title (String, (default: None)) –

    Title of the figure.
    • ’Scatterplot’

  • filepath (String, (Default: user temp directory)) –

    File path to save the output.
    • Temporarily path: ‘d3blocks.html’

    • Relative path: ‘./d3blocks.html’

    • Absolute path: ‘c://temp//d3blocks.html’

    • None: Return HTML

  • figsize (tuple) –

    Size of the figure in the browser, [width, height].
    • [900, 600]

  • showfig (bool, (default: True)) –

    • True: Open browser-window.

    • False: Do not open browser-window.

  • overwrite (bool, (default: True)) –

    • True: Overwrite the html in the destination directory.

    • False: Do not overwrite destination file but show warning instead.

  • notebook (bool) –

    • True: Use IPython to show chart in notebook.

    • False: Do not use IPython.

  • save_button (bool, (default: True)) –

    • True: Save button is shown in the HTML to save the image in svg.

    • False: No save button is shown in the HTML.

  • return_html (bool, (default: False)) –

    • True: Return html

    • False: Nothing is returned

  • reset_properties (bool, (default: True)) –

    • True: Reset the node_properties at each run.

    • False: Use the d3.node_properties()

Returns:

  • d3.node_properties (DataFrame of dictionary) – Contains properties of the unique input label/nodes/samples.

  • d3.edge_properties (DataFrame of dictionary) – Contains properties of the unique input edges/links.

  • d3.config (dictionary) – Contains configuration properties.

Examples

>>> # Load d3blocks
>>> from d3blocks import D3Blocks
>>>
>>> # Initialize
>>> d3 = D3Blocks(chart='Scatter')
>>>
>>> # Import example
>>> df = d3.import_example('cancer')
>>>
>>> # Set properties
>>> d3.set_node_properties(df)
>>>
>>> # Set properties
>>> d3.set_edge_properties(df['tsneX'].values,
>>>                        df['tsneY'].values,
>>>                        x1=df['PC1'].values,
>>>                        y1=df['PC2'].values,
>>>                        size=df['survival_months'].fillna(1).values / 10,
>>>                        color=df['labx'].values,
>>>                        opacity=0.5,
>>>                        tooltip=df['labx'].values + ' <br> Survival: ' + df['survival_months'].astype(str).str[0:4].values,
>>>                        scale=True,
>>>                        )
>>>
>>> d3.show(label_radio=['tSNE','PCA'])

Examples

>>> import pandas as pd
>>> import numpy as np
>>>
>>> # Load d3blocks
>>> from d3blocks import D3Blocks
>>>
>>> # Initialize
>>> d3 = D3Blocks(chart='Scatter')
>>>
>>> # Import example
>>> df = d3.import_example('cancer')
>>>
>>> # Set properties
>>> d3.set_node_properties(df)
>>>
>>> size=(df['survival_months'].fillna(1)/10)
>>> color=df['labx']
>>>
>>> tooltip = df['labx'].values + ' <br> Survival: ' + df['survival_months'].astype(str).str[0:4].values
>>> tooltip[0] = r'URL image and Image: <br><br> https://www.topdesk.com/en/wp-content/media/sites/30/SD-memes-Paper-jam-2.jpg <br> <br> With great audio too: <br><br> https://samplelib.com/mp3/sample-12s.mp3'
>>> tooltip[1] = r'Local image: <br><br><PATH TO YOUR IMAGE>'
>>> tooltip[2] = r'URL audio file: <br><br> https://samplelib.com/mp3/sample-3s.mp3'
>>> tooltip[3] = r'local audio file: <br><br> /data/50_speakers_audio/Speaker_0000/Speaker_0000_00030.wav'
>>> size[0]=30
>>> size[1]=30
>>> size[2]=30
>>> size[3]=30
>>> color[0] = 'special'
>>> color[1] = 'special'
>>> color[2] = 'special'
>>> color[3] = 'special'
>>>
>>> # Set properties
>>> d3.set_edge_properties(df['tsneX'].values,
>>>                        df['tsneY'].values,
>>>                        x1=df['PC1'].values,
>>>                        y1=df['PC2'].values,
>>>                        size=size,
>>>                        color=color,
>>>                        opacity=0.5,
>>>                        tooltip=tooltip,
>>>                        scale=True,
>>>                        )
>>>
>>> d3.show(label_radio=['tSNE','PCA'])

Examples

>>> from d3blocks import D3Blocks
>>> import numpy as np
>>>
>>> # Initialize
>>> d3 = D3Blocks(chart='Scatter')
>>>
>>> # Load example data
>>> df = d3.import_example('mnist')
>>>
>>> d3.set_node_properties(df)
>>>
>>> size = np.random.randint(0, 8, df.shape[0])
>>> opacity = np.random.randint(0, 8, df.shape[0])/10
>>> tooltip = df['y'].values.astype(str)
>>>
>>> # Set all propreties
>>> d3.set_edge_properties(df['PC1'].values,                   # PC1 x-coordinates
>>>            df['PC2'].values,                   # PC2 y-coordinates
>>>            x1=df['tsne_1'].values,             # tSNE x-coordinates
>>>            y1=df['tsne_2'].values,             # tSNE y-coordinates
>>>            color=df['y'].values.astype(str),   # Hex-colors or classlabels
>>>            tooltip=tooltip,                    # Tooltip
>>>            size=size,                          # Node size
>>>            opacity=opacity,                    # Opacity
>>>            stroke='#000000',
>>>            cmap='tab20',                       # Colormap
>>>            scale=True,                         # Scale the datapoints
>>>            label_radio=['PCA', 'tSNE'],
>>>            showfig=False,
>>>            )
>>>
>>> d3.show(filepath='scatter_demo.html', label_radio=['PCA', 'tSNE'], showfig=True)

Examples

>>> # Load d3blocks
>>> from d3blocks import D3Blocks
>>> #
>>> # Initialize
>>> d3 = D3Blocks(chart='Scatter')
>>> #
>>> # Import example
>>> df = d3.import_example('cancer')
>>> #
>>> # Set properties
>>> d3.set_node_properties(df)
>>> #
>>> # Set properties
>>> d3.set_edge_properties(df['tsneX'].values,
                           df['tsneY'].values,
                           x1=df['PC1'].values,
                           y1=df['PC2'].values,
                           label_radio=['tSNE','PCA'],
                           size=df['survival_months'].fillna(1).values / 10,
                           color=df['labx'].values,
                           tooltip=df['labx'].values + ' <br /> Survival: ' + df['survival_months'].astype(str).str[0:4].values,
                           scale=True)
>>> #
>>> # Show the chart
>>> d3.show()
>>> #
>>> # Set specific node properties.
>>> print(d3.edge_properties)
>>> d3.edge_properties[0]['size']=50
>>> d3.edge_properties[0]['color']='#000000'
>>> d3.edge_properties[0]['tooltip']='I am adjusted!'
>>> #
>>> # Configuration can be changed too.
>>> print(d3.config)
>>> #
>>> # Show the chart again with adjustments
>>> d3.show()

References

Strengths

The scatter chart is one of the most flexible building blocks in d3blocks because it is not limited to plotting x/y coordinates. It is designed to turn a table of samples and properties into an explorable map:

  • Interactive by design. Points can be panned, zoomed, hovered, and brushed (rectangular selection) directly in the browser, without regenerating the plot.

  • Multiple visual encodings at once. Color, size, opacity and labels can each be mapped to a different column, so several dimensions of the data can be inspected simultaneously on top of the x/y layout.

  • Adjustable, intuitive controls. Sliders — including dual-thumb range sliders for things such as the pixel bounds a point is allowed to render at — let the end-user reshape the chart live, without touching code.

  • Transitions between coordinate systems. The same set of points can smoothly animate between two or three different x/y layouts (e.g. PCA vs. t-SNE vs. UMAP coordinates), which makes it easy to compare embeddings or track how samples move between representations.

  • Scales to large datasets. Because rendering happens with D3/SVG in the browser, scatter plots with thousands of points remain responsive.

  • Built-in statistical exploration. Selecting a subset of points (e.g. via brushing) triggers an on-the-fly statistical association test against every other column in the dataset, surfacing which features are significantly enriched in the selection. This is described in detail in the Statistical Associations section below.

  • Composable output. Like other d3blocks charts, the result is a self-contained, shareable HTML file that requires no server or notebook to view it.

Input Data

The input dataset are the x-coordinates and y-coordinates that needs to be specified seperately.

#                 x          y   age  ... labels
# labels                              ...
# acc     37.204296  24.162813  58.0  ...    acc
# acc     37.093090  23.423557  44.0  ...    acc
# acc     36.806297  23.444910  23.0  ...    acc
# acc     38.067886  24.411770  30.0  ...    acc
# acc     36.791195  21.715324  29.0  ...    acc
#           ...        ...   ...  ...    ...
# brca     0.839383  -8.870781   NaN  ...   brca
# brca    -5.842904   2.877595   NaN  ...   brca
# brca    -9.392038   1.663352  71.0  ...   brca
# brca    -4.016389   6.260741   NaN  ...   brca
# brca     0.229801  -8.227086   NaN  ...   brca

# [4674 rows x 9 columns]

Chart

Default scatterplot

Transitions (2 coordinates)

Transitions (3 coordinates)

Statistical Associations

Alongside the visual encodings, the scatter chart can compute statistical associations between a selection of points and every other property column in the dataset. Selecting a group of points (e.g. by brushing a region of the plot) defines a binary label y — 1 for samples inside the selection, 0 for the rest — and each remaining column is then tested for whether it is significantly enriched in that selection. The results are ranked and shown in a stats panel next to the chart, so associations can be discovered interactively rather than being computed up front in a notebook.

The methodology mirrors the enrichment approach used in HNet: Graphical Hypergeometric Networks, applied here at plot-interaction time instead of over an entire graph. Two different tests are used depending on the data type of the column being compared against the selection.

Categorical features: hypergeometric test

For a categorical column, each category is treated as a separate binary feature (present / absent per sample), and its overlap with the selection is tested with a one-sided hypergeometric test — the same “over-representation” test HNet uses to decide whether an edge between two categorical nodes is significant.

Given:

  • \(M\) — the total number of samples,

  • \(n\) — the number of samples that have the category of interest,

  • \(N\) — the number of samples in the selection,

  • \(x\) — the observed overlap between the category and the selection,

the probability of seeing an overlap at least as large as the one observed, by chance, is:

\[P(X \geq x) = \sum_{i=x}^{\min(n, N)} \frac{\binom{n}{i}\binom{M-n}{N-i}}{\binom{M}{N}}\]

A small p-value means the category is over-represented in the selection far more than would be expected if samples were assigned to it at random — i.e. the category and the selection are statistically associated. Categories with fewer than two occurrences are skipped as too small to test meaningfully, and where a column only has two categories (e.g. True/False or 0/1), the background/negative class is not tested on its own — only the positive class is, matching HNet’s two-class handling.

Numerical features: Mann-Whitney U test

For a numeric column, the values of samples inside the selection are compared against the values of the samples outside it using the Mann-Whitney U test (equivalently, the Wilcoxon rank-sum test) — a non-parametric test that does not assume the values are normally distributed, which is what HNet uses for numeric-to-categorical comparisons.

All values are pooled and ranked (tied values receive the average of the ranks they span). If the selection group has \(n_1\) samples with summed rank \(R_1\), and the rest of the data has \(n_2\) samples, the U statistic and its normal approximation are:

\[U_1 = R_1 - \frac{n_1 (n_1 + 1)}{2}\]
\[z = \frac{U_1 - \dfrac{n_1 n_2}{2}}{\sqrt{\dfrac{n_1 n_2 (n_1 + n_2 + 1)}{12}}}\]

The two-sided p-value is then obtained from the standard normal CDF, \(\Phi\):

\[P = 2 \left(1 - \Phi(|z|)\right)\]

A small p-value indicates the numeric column’s distribution differs meaningfully between the selected samples and the rest (e.g. the selection tends to have systematically higher or lower values), rather than the difference being attributable to chance. Alongside the p-value, the mean, sample standard deviation and median are also reported for both groups, so an association can be interpreted in terms of effect direction and size — not only significance.

Multiple testing correction

Because a p-value is computed independently for every category and every numeric column, testing many columns at once inflates the chance of false positives. To control this, the raw p-values are corrected before filtering on significance, using one of:

  • Holm-Bonferroni (default) — a step-down procedure that is less conservative than a plain Bonferroni correction while still strongly controlling the family-wise error rate.

  • Bonferroni — the classical correction, which simply scales each p-value by the number of tests performed.

Only associations whose adjusted p-value (Padj) falls below the significance threshold alpha (default 0.05) are kept, and the surviving associations are sorted by Padj so the strongest, most reliable associations surface first in the stats panel.

Tip

The underlying enrichment engine is dependency-free JavaScript (no server round-trip needed) and can also be called directly, independent of the chart: D3BlocksAssociations.enrichment(columns, yBits, alpha, dtypeOverrides, multtest) returns the filtered, sorted list of significant associations for a set of columns and a binary selection mask.