lets-plot 4.7.0rc1__cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lets-plot might be problematic. Click here for more details.
- lets_plot/__init__.py +283 -0
- lets_plot/_global_settings.py +196 -0
- lets_plot/_kbridge.py +141 -0
- lets_plot/_type_utils.py +133 -0
- lets_plot/_version.py +6 -0
- lets_plot/bistro/__init__.py +16 -0
- lets_plot/bistro/_plot2d_common.py +100 -0
- lets_plot/bistro/corr.py +447 -0
- lets_plot/bistro/im.py +196 -0
- lets_plot/bistro/joint.py +192 -0
- lets_plot/bistro/qq.py +207 -0
- lets_plot/bistro/residual.py +341 -0
- lets_plot/bistro/waterfall.py +333 -0
- lets_plot/export/__init__.py +6 -0
- lets_plot/export/ggsave_.py +141 -0
- lets_plot/frontend_context/__init__.py +8 -0
- lets_plot/frontend_context/_configuration.py +151 -0
- lets_plot/frontend_context/_frontend_ctx.py +16 -0
- lets_plot/frontend_context/_html_contexts.py +117 -0
- lets_plot/frontend_context/_intellij_python_json_ctx.py +38 -0
- lets_plot/frontend_context/_json_contexts.py +39 -0
- lets_plot/frontend_context/_jupyter_notebook_ctx.py +119 -0
- lets_plot/frontend_context/_mime_types.py +7 -0
- lets_plot/frontend_context/_static_html_page_ctx.py +27 -0
- lets_plot/frontend_context/_static_svg_ctx.py +26 -0
- lets_plot/frontend_context/_webbr_html_page_ctx.py +29 -0
- lets_plot/frontend_context/sandbox.py +5 -0
- lets_plot/geo_data/__init__.py +19 -0
- lets_plot/geo_data/core.py +331 -0
- lets_plot/geo_data/geocoder.py +977 -0
- lets_plot/geo_data/geocodes.py +512 -0
- lets_plot/geo_data/gis/__init__.py +0 -0
- lets_plot/geo_data/gis/fluent_dict.py +201 -0
- lets_plot/geo_data/gis/geocoding_service.py +42 -0
- lets_plot/geo_data/gis/geometry.py +91 -0
- lets_plot/geo_data/gis/json_request.py +232 -0
- lets_plot/geo_data/gis/json_response.py +308 -0
- lets_plot/geo_data/gis/request.py +492 -0
- lets_plot/geo_data/gis/response.py +247 -0
- lets_plot/geo_data/livemap_helper.py +65 -0
- lets_plot/geo_data/to_geo_data_frame.py +141 -0
- lets_plot/geo_data/type_assertion.py +34 -0
- lets_plot/geo_data_internals/__init__.py +4 -0
- lets_plot/geo_data_internals/constants.py +13 -0
- lets_plot/geo_data_internals/utils.py +33 -0
- lets_plot/mapping.py +115 -0
- lets_plot/package_data/lets-plot.min.js +3 -0
- lets_plot/plot/__init__.py +64 -0
- lets_plot/plot/_global_theme.py +14 -0
- lets_plot/plot/annotation.py +290 -0
- lets_plot/plot/coord.py +242 -0
- lets_plot/plot/core.py +1060 -0
- lets_plot/plot/expand_limits_.py +78 -0
- lets_plot/plot/facet.py +206 -0
- lets_plot/plot/font_features.py +71 -0
- lets_plot/plot/geom.py +8839 -0
- lets_plot/plot/geom_extras.py +53 -0
- lets_plot/plot/geom_function_.py +216 -0
- lets_plot/plot/geom_imshow_.py +392 -0
- lets_plot/plot/geom_livemap_.py +310 -0
- lets_plot/plot/ggbunch_.py +96 -0
- lets_plot/plot/gggrid_.py +126 -0
- lets_plot/plot/ggtb_.py +55 -0
- lets_plot/plot/guide.py +229 -0
- lets_plot/plot/label.py +187 -0
- lets_plot/plot/marginal_layer.py +181 -0
- lets_plot/plot/plot.py +244 -0
- lets_plot/plot/pos.py +320 -0
- lets_plot/plot/sampling.py +338 -0
- lets_plot/plot/sandbox_.py +26 -0
- lets_plot/plot/scale.py +3577 -0
- lets_plot/plot/scale_colormap_mpl.py +297 -0
- lets_plot/plot/scale_convenience.py +155 -0
- lets_plot/plot/scale_identity_.py +658 -0
- lets_plot/plot/scale_position.py +1342 -0
- lets_plot/plot/series_meta.py +203 -0
- lets_plot/plot/stat.py +581 -0
- lets_plot/plot/subplots.py +322 -0
- lets_plot/plot/subplots_util.py +24 -0
- lets_plot/plot/theme_.py +772 -0
- lets_plot/plot/theme_set.py +393 -0
- lets_plot/plot/tooltip.py +486 -0
- lets_plot/plot/util.py +237 -0
- lets_plot/settings_utils.py +244 -0
- lets_plot/tilesets.py +429 -0
- lets_plot-4.7.0rc1.dist-info/METADATA +196 -0
- lets_plot-4.7.0rc1.dist-info/RECORD +95 -0
- lets_plot-4.7.0rc1.dist-info/WHEEL +6 -0
- lets_plot-4.7.0rc1.dist-info/licenses/LICENSE +21 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
- lets_plot-4.7.0rc1.dist-info/top_level.txt +2 -0
- lets_plot_kotlin_bridge.cpython-39-aarch64-linux-gnu.so +0 -0
lets_plot/_type_utils.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2019. JetBrains s.r.o.
|
|
3
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
import json
|
|
6
|
+
import math
|
|
7
|
+
from datetime import datetime, date, time, timezone
|
|
8
|
+
|
|
9
|
+
from typing import Dict
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
import numpy
|
|
13
|
+
except ImportError:
|
|
14
|
+
numpy = None
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
import pandas
|
|
18
|
+
except ImportError:
|
|
19
|
+
pandas = None
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
import polars
|
|
23
|
+
except ImportError:
|
|
24
|
+
polars = None
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
import shapely
|
|
28
|
+
import shapely.geometry
|
|
29
|
+
except ImportError:
|
|
30
|
+
shapely = None
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
import jax.numpy as jnp
|
|
34
|
+
except ImportError:
|
|
35
|
+
jnp = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Parameter 'value' can also be pandas.DataFrame
|
|
39
|
+
def standardize_dict(value: Dict) -> Dict:
|
|
40
|
+
result = {}
|
|
41
|
+
for k, v in value.items():
|
|
42
|
+
result[_standardize_value(k)] = _standardize_value(v)
|
|
43
|
+
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def is_pandas_data_frame(v) -> bool:
|
|
48
|
+
return pandas and isinstance(v, pandas.DataFrame)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_polars_dataframe(v):
|
|
52
|
+
return polars and isinstance(v, polars.DataFrame)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def is_dict_or_dataframe(v):
|
|
56
|
+
return isinstance(v, dict) or (pandas and isinstance(v, pandas.DataFrame))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def is_int(v):
|
|
60
|
+
return isinstance(v, int) or (numpy and isinstance(v, numpy.integer)) or (jnp and isinstance(v, jnp.integer))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def is_float(v):
|
|
64
|
+
return isinstance(v, float) or (numpy and isinstance(v, numpy.floating)) or (jnp and isinstance(v, jnp.floating))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def is_ndarray(data) -> bool:
|
|
68
|
+
return (numpy and isinstance(data, numpy.ndarray)) or (jnp and isinstance(data, jnp.ndarray))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def is_number(v):
|
|
72
|
+
return is_int(v) or is_float(v)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _standardize_value(v):
|
|
76
|
+
if v is None:
|
|
77
|
+
return v
|
|
78
|
+
if isinstance(v, bool):
|
|
79
|
+
return bool(v)
|
|
80
|
+
if isinstance(v, str):
|
|
81
|
+
return str(v)
|
|
82
|
+
if is_float(v):
|
|
83
|
+
if math.isfinite(v):
|
|
84
|
+
return float(v)
|
|
85
|
+
# None for special values like 'nan' etc. because
|
|
86
|
+
# some JSON parsers (like com.google.gson.Gson) do not handle them well.
|
|
87
|
+
return None
|
|
88
|
+
if is_int(v):
|
|
89
|
+
return float(v)
|
|
90
|
+
if is_dict_or_dataframe(v):
|
|
91
|
+
return standardize_dict(v)
|
|
92
|
+
if is_polars_dataframe(v):
|
|
93
|
+
return standardize_dict(v.to_dict(as_series=False))
|
|
94
|
+
if isinstance(v, list):
|
|
95
|
+
return [_standardize_value(elem) for elem in v]
|
|
96
|
+
if isinstance(v, tuple):
|
|
97
|
+
return tuple(_standardize_value(elem) for elem in v)
|
|
98
|
+
|
|
99
|
+
if (numpy and isinstance(v, numpy.ndarray)):
|
|
100
|
+
# Process each array element individually.
|
|
101
|
+
# Don't use '.tolist()' because this will implicitly
|
|
102
|
+
# convert 'datetime64' values to unpredictable 'datetime' objects.
|
|
103
|
+
return [_standardize_value(x) for x in v]
|
|
104
|
+
|
|
105
|
+
if (pandas and isinstance(v, pandas.Series)) or (jnp and isinstance(v, jnp.ndarray)):
|
|
106
|
+
return _standardize_value(v.tolist())
|
|
107
|
+
|
|
108
|
+
# Universal NaT/NaN check
|
|
109
|
+
if pandas and pandas.isna(v):
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
if isinstance(v, datetime):
|
|
113
|
+
# Datetime: to milliseconds since epoch (time zone aware)
|
|
114
|
+
return v.timestamp() * 1000
|
|
115
|
+
if isinstance(v, date):
|
|
116
|
+
# Local date: to milliseconds since epoch (midnight UTC)
|
|
117
|
+
return datetime.combine(v, time.min, tzinfo=timezone.utc).timestamp() * 1000
|
|
118
|
+
if isinstance(v, time):
|
|
119
|
+
# Local time: to milliseconds since midnight
|
|
120
|
+
return float(v.hour * 3600_000 + v.minute * 60_000 + v.second * 1000 + v.microsecond // 1000)
|
|
121
|
+
if numpy and isinstance(v, numpy.datetime64):
|
|
122
|
+
try:
|
|
123
|
+
# numpy.datetime64: to milliseconds since epoch (Unix time)
|
|
124
|
+
return float(v.astype('datetime64[ms]').astype(numpy.int64))
|
|
125
|
+
except:
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
if shapely and isinstance(v, shapely.geometry.base.BaseGeometry):
|
|
129
|
+
return json.dumps(shapely.geometry.mapping(v))
|
|
130
|
+
try:
|
|
131
|
+
return repr(v)
|
|
132
|
+
except Exception:
|
|
133
|
+
raise Exception('Unsupported type: {0}({1})'.format(v, type(v)))
|
lets_plot/_version.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Copyright (c) 2020. JetBrains s.r.o.
|
|
2
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
3
|
+
|
|
4
|
+
from .corr import *
|
|
5
|
+
from .im import *
|
|
6
|
+
from .qq import *
|
|
7
|
+
from .residual import *
|
|
8
|
+
from .joint import *
|
|
9
|
+
from .waterfall import *
|
|
10
|
+
|
|
11
|
+
__all__ = (im.__all__ +
|
|
12
|
+
corr.__all__ +
|
|
13
|
+
qq.__all__ +
|
|
14
|
+
residual.__all__ +
|
|
15
|
+
joint.__all__ +
|
|
16
|
+
waterfall.__all__)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2023. JetBrains s.r.o.
|
|
3
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
from ..plot.core import DummySpec, aes
|
|
6
|
+
from ..plot.geom import *
|
|
7
|
+
from ..plot.marginal_layer import ggmarginal
|
|
8
|
+
|
|
9
|
+
_BINS_DEF = 30
|
|
10
|
+
_COLOR_DEF = "pen"
|
|
11
|
+
|
|
12
|
+
_MARGINAL_ALPHA = .1
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_bin_params_2d(xs, ys, binwidth, bins):
|
|
16
|
+
if isinstance(bins, int):
|
|
17
|
+
bins = [bins, bins]
|
|
18
|
+
if isinstance(binwidth, int) or isinstance(binwidth, float):
|
|
19
|
+
binwidth = [binwidth, binwidth]
|
|
20
|
+
if binwidth is not None or bins is not None or len(xs) == 0:
|
|
21
|
+
return binwidth, bins
|
|
22
|
+
binwidth_x = (max(xs) - min(xs)) / _BINS_DEF
|
|
23
|
+
binwidth_y = (max(ys) - min(ys)) / _BINS_DEF
|
|
24
|
+
binwidth_max = max(binwidth_x, binwidth_y)
|
|
25
|
+
|
|
26
|
+
return [binwidth_max, binwidth_max], bins
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _get_geom2d_layer(geom_kind, binwidth2d, bins2d, color, color_by, size, alpha, show_legend):
|
|
30
|
+
if geom_kind == 'point':
|
|
31
|
+
return geom_point(color=color, size=size, alpha=alpha, show_legend=show_legend)
|
|
32
|
+
if geom_kind == 'tile':
|
|
33
|
+
return geom_bin2d(
|
|
34
|
+
aes(fill=('..count..' if color_by is None else color_by)),
|
|
35
|
+
bins=bins2d, binwidth=binwidth2d,
|
|
36
|
+
color=color, size=size, alpha=alpha,
|
|
37
|
+
show_legend=show_legend
|
|
38
|
+
)
|
|
39
|
+
if geom_kind == 'hex':
|
|
40
|
+
return geom_hex(
|
|
41
|
+
aes(fill=('..count..' if color_by is None else color_by)),
|
|
42
|
+
bins=bins2d, binwidth=binwidth2d,
|
|
43
|
+
color=color, size=size, alpha=alpha,
|
|
44
|
+
show_legend=show_legend
|
|
45
|
+
)
|
|
46
|
+
if geom_kind == 'density2d':
|
|
47
|
+
return geom_density2d(
|
|
48
|
+
aes(color=('..group..' if color_by is None else color_by)),
|
|
49
|
+
color=color, size=size, alpha=alpha,
|
|
50
|
+
show_legend=show_legend
|
|
51
|
+
)
|
|
52
|
+
if geom_kind == 'density2df':
|
|
53
|
+
return geom_density2df(
|
|
54
|
+
aes(fill=('..group..' if color_by is None else color_by)),
|
|
55
|
+
color=color, size=size, alpha=alpha,
|
|
56
|
+
show_legend=show_legend
|
|
57
|
+
)
|
|
58
|
+
if geom_kind == 'none':
|
|
59
|
+
return None
|
|
60
|
+
raise Exception("Unknown geom '{0}'".format(geom_kind))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _get_marginal_layers(marginal, binwidth2d, bins2d, color, color_by, show_legend):
|
|
64
|
+
marginal_color = None if color_by is not None else (color or _COLOR_DEF)
|
|
65
|
+
|
|
66
|
+
def bin_param_to_1d(param2d, side):
|
|
67
|
+
if param2d is None:
|
|
68
|
+
return None
|
|
69
|
+
else:
|
|
70
|
+
if side in ['t', 'b']:
|
|
71
|
+
return param2d[0]
|
|
72
|
+
else:
|
|
73
|
+
return param2d[1]
|
|
74
|
+
|
|
75
|
+
def _get_marginal_layer(geom_kind, side, size):
|
|
76
|
+
if geom_kind in ['dens', 'density']:
|
|
77
|
+
layer = geom_area(stat='density', position='identity', color=marginal_color, fill=marginal_color,
|
|
78
|
+
alpha=_MARGINAL_ALPHA, show_legend=show_legend)
|
|
79
|
+
elif geom_kind in ['hist', 'histogram']:
|
|
80
|
+
binwidth = bin_param_to_1d(binwidth2d, side)
|
|
81
|
+
bins = bin_param_to_1d(bins2d, side)
|
|
82
|
+
layer = geom_histogram(bins=bins, binwidth=binwidth,
|
|
83
|
+
color=marginal_color, fill=marginal_color, alpha=_MARGINAL_ALPHA,
|
|
84
|
+
show_legend=show_legend)
|
|
85
|
+
elif geom_kind in ['box', 'boxplot']:
|
|
86
|
+
layer = geom_boxplot(color=marginal_color, fill=marginal_color, alpha=_MARGINAL_ALPHA, show_legend=show_legend)
|
|
87
|
+
else:
|
|
88
|
+
raise Exception("Unknown geom '{0}'".format(geom_kind))
|
|
89
|
+
|
|
90
|
+
return ggmarginal(side, size=size, layer=layer)
|
|
91
|
+
|
|
92
|
+
result = DummySpec()
|
|
93
|
+
for layer_description in filter(bool, marginal.split(",")):
|
|
94
|
+
params = layer_description.strip().split(":")
|
|
95
|
+
geom_kind, sides = params[0].strip(), params[1].strip()
|
|
96
|
+
size = float(params[2].strip()) if len(params) > 2 else None
|
|
97
|
+
for side in sides:
|
|
98
|
+
result += _get_marginal_layer(geom_kind, side, size)
|
|
99
|
+
|
|
100
|
+
return result
|
lets_plot/bistro/corr.py
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
# Copyright (c) 2020. JetBrains s.r.o.
|
|
2
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
"""Correlation matrix implementation module"""
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from lets_plot.plot.util import is_pandas_data_frame
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import numpy
|
|
12
|
+
except ImportError:
|
|
13
|
+
numpy = None
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
import pandas
|
|
17
|
+
except ImportError:
|
|
18
|
+
pandas = None
|
|
19
|
+
|
|
20
|
+
from lets_plot.plot.core import PlotSpec
|
|
21
|
+
|
|
22
|
+
__all__ = ['corr_plot']
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _is_corr_matrix(data: Any):
|
|
26
|
+
if is_pandas_data_frame(data):
|
|
27
|
+
if data.shape[0] != data.shape[1]:
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
if not (all(col_type == 'float64' for col_type in data.dtypes)):
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
for column in data:
|
|
34
|
+
import math
|
|
35
|
+
if not all(math.isnan(v) or (1.0 >= v >= -1.0) for v in data[column]):
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
elif isinstance(data, dict):
|
|
41
|
+
m = len(data.keys())
|
|
42
|
+
for column in data.values():
|
|
43
|
+
if not isinstance(column, (list, tuple)):
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
if len(column) != m:
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
import math
|
|
50
|
+
for v in column:
|
|
51
|
+
if not isinstance(v, float):
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
if math.isnan(v):
|
|
55
|
+
return True
|
|
56
|
+
|
|
57
|
+
if 1.0 >= v >= -1.0:
|
|
58
|
+
return True
|
|
59
|
+
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
return True
|
|
63
|
+
else:
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class corr_plot:
|
|
68
|
+
"""
|
|
69
|
+
This class is intended to build correlation matrix plot.
|
|
70
|
+
|
|
71
|
+
Notes
|
|
72
|
+
-----
|
|
73
|
+
To hide axis tooltips, set 'blank' or the result of `element_blank()`
|
|
74
|
+
to the `axis_tooltip`, `axis_tooltip_x` or `axis_tooltip_y` parameter of the `theme()`.
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
.. jupyter-execute::
|
|
79
|
+
:linenos:
|
|
80
|
+
:emphasize-lines: 7
|
|
81
|
+
|
|
82
|
+
import numpy as np
|
|
83
|
+
from lets_plot import *
|
|
84
|
+
from lets_plot.bistro.corr import *
|
|
85
|
+
LetsPlot.setup_html()
|
|
86
|
+
np.random.seed(42)
|
|
87
|
+
data = {var: np.random.poisson(size=10) for var in 'abcdef'}
|
|
88
|
+
corr_plot(data).tiles().build()
|
|
89
|
+
|
|
90
|
+
|
|
|
91
|
+
|
|
92
|
+
.. jupyter-execute::
|
|
93
|
+
:linenos:
|
|
94
|
+
:emphasize-lines: 7-9
|
|
95
|
+
|
|
96
|
+
import numpy as np
|
|
97
|
+
from lets_plot import *
|
|
98
|
+
from lets_plot.bistro.corr import *
|
|
99
|
+
LetsPlot.setup_html()
|
|
100
|
+
np.random.seed(42)
|
|
101
|
+
data = {var: np.random.uniform(size=10) for var in 'abcd'}
|
|
102
|
+
corr_plot(data).tiles(type='upper', diag=True)\\
|
|
103
|
+
.labels(type='upper', diag=True, map_size=True, color='black')\\
|
|
104
|
+
.palette_RdBu().build()
|
|
105
|
+
|
|
106
|
+
|
|
|
107
|
+
|
|
108
|
+
.. jupyter-execute::
|
|
109
|
+
:linenos:
|
|
110
|
+
:emphasize-lines: 7-9
|
|
111
|
+
|
|
112
|
+
import numpy as np
|
|
113
|
+
from lets_plot import *
|
|
114
|
+
from lets_plot.bistro.corr import *
|
|
115
|
+
LetsPlot.setup_html()
|
|
116
|
+
np.random.seed(42)
|
|
117
|
+
data = {var: np.random.normal(size=10) for var in 'abcdef'}
|
|
118
|
+
corr_plot(data, flip=False, threshold=.4).points().labels()\\
|
|
119
|
+
.palette_gradient(low='#d73027', mid='#ffffbf', high='#1a9850')\\
|
|
120
|
+
.build()
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
def _duplicate(self):
|
|
125
|
+
dup = corr_plot(
|
|
126
|
+
data=self._data,
|
|
127
|
+
show_legend=self._show_legend,
|
|
128
|
+
flip=self._reverse_y,
|
|
129
|
+
threshold=self.threshold
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
dup._color_scale = self._color_scale
|
|
133
|
+
dup._fill_scale = self._fill_scale
|
|
134
|
+
dup._points_params = self._points_params
|
|
135
|
+
dup._tiles_params = self._tiles_params
|
|
136
|
+
dup._labels_params = self._labels_params
|
|
137
|
+
dup._labels_map_size = self._labels_map_size
|
|
138
|
+
dup._palette = self._palette
|
|
139
|
+
dup._low = self._low
|
|
140
|
+
dup._mid = self._mid
|
|
141
|
+
dup._high = self._high
|
|
142
|
+
|
|
143
|
+
return dup
|
|
144
|
+
|
|
145
|
+
def __init__(self, data, show_legend=True, flip=True, threshold=None):
|
|
146
|
+
"""
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
data : dict or Pandas or Polars `DataFrame`
|
|
150
|
+
Correlation matrix or data (correlation will be calculated for each variable pair).
|
|
151
|
+
Data will be recognized as correlation matrix if it has a square shape and all values are
|
|
152
|
+
in range -1.0..+1.0 or NaN.
|
|
153
|
+
show_legend : bool, default=True
|
|
154
|
+
If True legend is shown.
|
|
155
|
+
flip : bool, default=True
|
|
156
|
+
If True the y axis is flipped.
|
|
157
|
+
threshold : float, default=0.0
|
|
158
|
+
Minimal correlation abs value to be included in result.
|
|
159
|
+
Accept values between 0 and 1.
|
|
160
|
+
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
self._data = data
|
|
164
|
+
self._show_legend = show_legend
|
|
165
|
+
self._reverse_y = flip if flip else False
|
|
166
|
+
self.threshold = threshold
|
|
167
|
+
self._color_scale = None
|
|
168
|
+
self._fill_scale = None
|
|
169
|
+
self._points_params = None
|
|
170
|
+
self._tiles_params = None
|
|
171
|
+
self._labels_params = None
|
|
172
|
+
self._labels_map_size = None
|
|
173
|
+
self._palette = None
|
|
174
|
+
self._low = None
|
|
175
|
+
self._mid = None
|
|
176
|
+
self._high = None
|
|
177
|
+
|
|
178
|
+
def points(self, type=None, diag=None):
|
|
179
|
+
"""
|
|
180
|
+
Method defines correlation matrix layer drawn by points to the plot.
|
|
181
|
+
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
type : {'upper', 'lower', 'full'}
|
|
185
|
+
Type of matrix. Default - contextual.
|
|
186
|
+
diag : bool
|
|
187
|
+
Determines whether to fill the main diagonal with values or not.
|
|
188
|
+
Default - contextual.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
`corr_plot`
|
|
193
|
+
Correlation plot specification.
|
|
194
|
+
"""
|
|
195
|
+
return self._duplicate()._set_points(type, diag)
|
|
196
|
+
|
|
197
|
+
def labels(self, type=None, diag=None, map_size=None, color=None):
|
|
198
|
+
"""
|
|
199
|
+
Method defines correlation matrix layer drawn with geom_text to the plot.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
type : {'upper', 'lower', 'full'}
|
|
204
|
+
Type of matrix. Default - contextual.
|
|
205
|
+
diag : bool
|
|
206
|
+
Determines whether to fill the main diagonal with values or not.
|
|
207
|
+
Default - contextual.
|
|
208
|
+
map_size : bool
|
|
209
|
+
If True, then absolute value of correlation is mapped to text size.
|
|
210
|
+
If False - the text size is constant. Default - contextual.
|
|
211
|
+
color : str
|
|
212
|
+
Set text color.
|
|
213
|
+
For more info see `Color and Fill <https://lets-plot.org/python/pages/aesthetics.html#color-and-fill>`__.
|
|
214
|
+
Default - contextual.
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
`corr_plot`
|
|
219
|
+
Correlation plot specification.
|
|
220
|
+
"""
|
|
221
|
+
return self._duplicate()._set_labels(type, diag, map_size, color)
|
|
222
|
+
|
|
223
|
+
def tiles(self, type=None, diag=None):
|
|
224
|
+
"""
|
|
225
|
+
Method defines correlation matrix layer drawn as square tiles to the plot.
|
|
226
|
+
|
|
227
|
+
Parameters
|
|
228
|
+
----------
|
|
229
|
+
type : {'upper', 'lower', 'full'}
|
|
230
|
+
Type of matrix. Default - contextual.
|
|
231
|
+
diag : bool
|
|
232
|
+
Determines whether to fill the main diagonal with values or not.
|
|
233
|
+
Default - contextual.
|
|
234
|
+
|
|
235
|
+
Returns
|
|
236
|
+
-------
|
|
237
|
+
`corr_plot`
|
|
238
|
+
Correlation plot specification.
|
|
239
|
+
"""
|
|
240
|
+
return self._duplicate()._set_tiles(type, diag)
|
|
241
|
+
|
|
242
|
+
def palette_gradient(self, low, mid, high):
|
|
243
|
+
"""
|
|
244
|
+
Set `scale_color_gradient2()` and `scale_fill_gradient()` for corr plot.
|
|
245
|
+
|
|
246
|
+
Parameters
|
|
247
|
+
----------
|
|
248
|
+
low : str
|
|
249
|
+
Color for low end of gradient (correlation -1).
|
|
250
|
+
mid : str
|
|
251
|
+
Color for mid point (correlation 0).
|
|
252
|
+
high : str
|
|
253
|
+
Color for high end of gradient (correlation 1).
|
|
254
|
+
|
|
255
|
+
Returns
|
|
256
|
+
-------
|
|
257
|
+
`corr_plot`
|
|
258
|
+
Correlation plot specification.
|
|
259
|
+
"""
|
|
260
|
+
return self._duplicate()._set_gradient_palette(low, mid, high)
|
|
261
|
+
|
|
262
|
+
def palette_BrBG(self):
|
|
263
|
+
"""
|
|
264
|
+
Set `scale_color_brewer()` with BrBG palette for corr plot.
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
`corr_plot`
|
|
269
|
+
Correlation plot specification.
|
|
270
|
+
"""
|
|
271
|
+
return self._set_brewer_palette('BrBG')
|
|
272
|
+
|
|
273
|
+
def palette_PiYG(self):
|
|
274
|
+
"""
|
|
275
|
+
Set `scale_color_brewer()` with PiYG palette for corr plot.
|
|
276
|
+
|
|
277
|
+
Returns
|
|
278
|
+
-------
|
|
279
|
+
`corr_plot`
|
|
280
|
+
Correlation plot specification.
|
|
281
|
+
"""
|
|
282
|
+
return self._duplicate()._set_brewer_palette('PiYG')
|
|
283
|
+
|
|
284
|
+
def palette_PRGn(self):
|
|
285
|
+
"""
|
|
286
|
+
Set `scale_color_brewer()` with PRGn palette for corr plot.
|
|
287
|
+
|
|
288
|
+
Returns
|
|
289
|
+
-------
|
|
290
|
+
`corr_plot`
|
|
291
|
+
Correlation plot specification.
|
|
292
|
+
"""
|
|
293
|
+
return self._duplicate()._set_brewer_palette('PRGn')
|
|
294
|
+
|
|
295
|
+
def palette_PuOr(self):
|
|
296
|
+
"""
|
|
297
|
+
Set `scale_color_brewer()` with PuOr palette for corr plot.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
`corr_plot`
|
|
302
|
+
Correlation plot specification.
|
|
303
|
+
"""
|
|
304
|
+
return self._duplicate()._set_brewer_palette('PuOr')
|
|
305
|
+
|
|
306
|
+
def palette_RdBu(self):
|
|
307
|
+
"""
|
|
308
|
+
Set `scale_color_brewer()` with RdBu palette for corr plot.
|
|
309
|
+
|
|
310
|
+
Returns
|
|
311
|
+
-------
|
|
312
|
+
`corr_plot`
|
|
313
|
+
Correlation plot specification.
|
|
314
|
+
"""
|
|
315
|
+
return self._duplicate()._set_brewer_palette('RdBu')
|
|
316
|
+
|
|
317
|
+
def palette_RdGy(self):
|
|
318
|
+
"""
|
|
319
|
+
Set `scale_color_brewer()` with RdGy palette for corr plot.
|
|
320
|
+
|
|
321
|
+
Returns
|
|
322
|
+
-------
|
|
323
|
+
`corr_plot`
|
|
324
|
+
Correlation plot specification.
|
|
325
|
+
"""
|
|
326
|
+
return self._duplicate()._set_brewer_palette('RdGy')
|
|
327
|
+
|
|
328
|
+
def palette_RdYlBu(self):
|
|
329
|
+
"""
|
|
330
|
+
Set `scale_color_brewer()` with RdYlBu palette for corr plot.
|
|
331
|
+
|
|
332
|
+
Returns
|
|
333
|
+
-------
|
|
334
|
+
`corr_plot`
|
|
335
|
+
Correlation plot specification.
|
|
336
|
+
"""
|
|
337
|
+
return self._duplicate()._set_brewer_palette('RdYlBu')
|
|
338
|
+
|
|
339
|
+
def palette_RdYlGn(self):
|
|
340
|
+
"""
|
|
341
|
+
Set `scale_color_brewer()` with RdYlGn palette for corr plot.
|
|
342
|
+
|
|
343
|
+
Returns
|
|
344
|
+
-------
|
|
345
|
+
`corr_plot`
|
|
346
|
+
Correlation plot specification.
|
|
347
|
+
"""
|
|
348
|
+
return self._duplicate()._set_brewer_palette('RdYlGn')
|
|
349
|
+
|
|
350
|
+
def palette_Spectral(self):
|
|
351
|
+
"""
|
|
352
|
+
Set `scale_color_brewer()` with Spectral palette for corr plot.
|
|
353
|
+
|
|
354
|
+
Returns
|
|
355
|
+
-------
|
|
356
|
+
`corr_plot`
|
|
357
|
+
Correlation plot specification.
|
|
358
|
+
"""
|
|
359
|
+
return self._duplicate()._set_brewer_palette('Spectral')
|
|
360
|
+
|
|
361
|
+
def _set_points(self, type=None, diag=None):
|
|
362
|
+
self._points_params = {'type': type, 'diag': diag, 'threshold': self.threshold}
|
|
363
|
+
return self
|
|
364
|
+
|
|
365
|
+
def _set_labels(self, type=None, diag=None, map_size=None, color=None):
|
|
366
|
+
self._labels_params = {'type': type, 'diag': diag, 'color': color, 'threshold': self.threshold}
|
|
367
|
+
self._labels_map_size = map_size
|
|
368
|
+
return self
|
|
369
|
+
|
|
370
|
+
def _set_tiles(self, type=None, diag=None):
|
|
371
|
+
self._tiles_params = {'type': type, 'diag': diag, 'threshold': self.threshold}
|
|
372
|
+
return self
|
|
373
|
+
|
|
374
|
+
def _set_gradient_palette(self, low, mid, high):
|
|
375
|
+
self._palette = 'gradient'
|
|
376
|
+
self._low = low
|
|
377
|
+
self._mid = mid
|
|
378
|
+
self._high = high
|
|
379
|
+
return self
|
|
380
|
+
|
|
381
|
+
def _set_brewer_palette(self, palette):
|
|
382
|
+
self._palette = palette
|
|
383
|
+
self._low = None
|
|
384
|
+
self._mid = None
|
|
385
|
+
self._high = None
|
|
386
|
+
return self
|
|
387
|
+
|
|
388
|
+
def build(self) -> PlotSpec:
|
|
389
|
+
"""
|
|
390
|
+
This method creates PlotSpec object.
|
|
391
|
+
|
|
392
|
+
Returns
|
|
393
|
+
-------
|
|
394
|
+
`PlotSpec`
|
|
395
|
+
Plot specification.
|
|
396
|
+
"""
|
|
397
|
+
|
|
398
|
+
if self._points_params is not None:
|
|
399
|
+
point_params = {
|
|
400
|
+
'type': self._points_params['type'],
|
|
401
|
+
'diag': self._points_params['diag']
|
|
402
|
+
}
|
|
403
|
+
else:
|
|
404
|
+
point_params = None
|
|
405
|
+
|
|
406
|
+
if self._labels_params is not None:
|
|
407
|
+
label_params = {
|
|
408
|
+
'type': self._labels_params['type'],
|
|
409
|
+
'diag': self._labels_params['diag'],
|
|
410
|
+
'color': self._labels_params['color'],
|
|
411
|
+
'map_size': self._labels_map_size
|
|
412
|
+
}
|
|
413
|
+
else:
|
|
414
|
+
label_params = None
|
|
415
|
+
|
|
416
|
+
if self._tiles_params is not None:
|
|
417
|
+
tile_params = {
|
|
418
|
+
'type': self._tiles_params['type'],
|
|
419
|
+
'diag': self._tiles_params['diag']
|
|
420
|
+
}
|
|
421
|
+
else:
|
|
422
|
+
tile_params = None
|
|
423
|
+
|
|
424
|
+
data = self._data
|
|
425
|
+
if _is_corr_matrix(data):
|
|
426
|
+
coefficients = True
|
|
427
|
+
else:
|
|
428
|
+
if is_pandas_data_frame(data):
|
|
429
|
+
data = data.corr(numeric_only=True)
|
|
430
|
+
coefficients = True
|
|
431
|
+
else:
|
|
432
|
+
coefficients = False
|
|
433
|
+
|
|
434
|
+
return PlotSpec(data=data, mapping=None, scales=[], layers=[], bistro={
|
|
435
|
+
'name': 'corr',
|
|
436
|
+
'coefficients': coefficients,
|
|
437
|
+
'show_legend': self._show_legend,
|
|
438
|
+
'flip': self._reverse_y,
|
|
439
|
+
'threshold': self.threshold,
|
|
440
|
+
'palette': self._palette,
|
|
441
|
+
'low': self._low,
|
|
442
|
+
'mid': self._mid,
|
|
443
|
+
'high': self._high,
|
|
444
|
+
'point_params': point_params,
|
|
445
|
+
'tile_params': tile_params,
|
|
446
|
+
'label_params': label_params
|
|
447
|
+
})
|