lets-plot 4.8.1rc1__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.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.
- lets_plot/__init__.py +382 -0
- lets_plot/_global_settings.py +192 -0
- lets_plot/_kbridge.py +197 -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 +106 -0
- lets_plot/bistro/corr.py +448 -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 +332 -0
- lets_plot/export/__init__.py +6 -0
- lets_plot/export/ggsave_.py +172 -0
- lets_plot/frontend_context/__init__.py +8 -0
- lets_plot/frontend_context/_configuration.py +140 -0
- lets_plot/frontend_context/_dynamic_configure_html.py +115 -0
- lets_plot/frontend_context/_frontend_ctx.py +16 -0
- lets_plot/frontend_context/_html_contexts.py +223 -0
- lets_plot/frontend_context/_intellij_python_json_ctx.py +38 -0
- lets_plot/frontend_context/_isolated_webview_panel_ctx.py +81 -0
- lets_plot/frontend_context/_json_contexts.py +39 -0
- lets_plot/frontend_context/_jupyter_notebook_ctx.py +82 -0
- lets_plot/frontend_context/_mime_types.py +7 -0
- lets_plot/frontend_context/_static_html_page_ctx.py +76 -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 +335 -0
- lets_plot/geo_data/geocoder.py +988 -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 +1071 -0
- lets_plot/plot/expand_limits_.py +78 -0
- lets_plot/plot/facet.py +210 -0
- lets_plot/plot/font_features.py +71 -0
- lets_plot/plot/geom.py +9146 -0
- lets_plot/plot/geom_extras.py +53 -0
- lets_plot/plot/geom_function_.py +219 -0
- lets_plot/plot/geom_imshow_.py +393 -0
- lets_plot/plot/geom_livemap_.py +343 -0
- lets_plot/plot/ggbunch_.py +96 -0
- lets_plot/plot/gggrid_.py +139 -0
- lets_plot/plot/ggtb_.py +81 -0
- lets_plot/plot/guide.py +231 -0
- lets_plot/plot/label.py +187 -0
- lets_plot/plot/marginal_layer.py +181 -0
- lets_plot/plot/plot.py +245 -0
- lets_plot/plot/pos.py +344 -0
- lets_plot/plot/sampling.py +338 -0
- lets_plot/plot/sandbox_.py +26 -0
- lets_plot/plot/scale.py +3580 -0
- lets_plot/plot/scale_colormap_mpl.py +300 -0
- lets_plot/plot/scale_convenience.py +155 -0
- lets_plot/plot/scale_identity_.py +653 -0
- lets_plot/plot/scale_position.py +1342 -0
- lets_plot/plot/series_meta.py +209 -0
- lets_plot/plot/stat.py +585 -0
- lets_plot/plot/subplots.py +331 -0
- lets_plot/plot/subplots_util.py +24 -0
- lets_plot/plot/theme_.py +790 -0
- lets_plot/plot/theme_set.py +418 -0
- lets_plot/plot/tooltip.py +486 -0
- lets_plot/plot/util.py +267 -0
- lets_plot/settings_utils.py +244 -0
- lets_plot/tilesets.py +429 -0
- lets_plot-4.8.1rc1.dist-info/METADATA +221 -0
- lets_plot-4.8.1rc1.dist-info/RECORD +97 -0
- lets_plot-4.8.1rc1.dist-info/WHEEL +6 -0
- lets_plot-4.8.1rc1.dist-info/licenses/LICENSE +21 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
- lets_plot-4.8.1rc1.dist-info/top_level.txt +2 -0
- lets_plot_kotlin_bridge.cpython-311-x86_64-linux-gnu.so +0 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Copyright (c) 2024. 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
|
+
from datetime import datetime, date, time
|
|
4
|
+
from typing import Union, Dict, Iterable, Optional
|
|
5
|
+
|
|
6
|
+
from lets_plot._type_utils import is_polars_dataframe
|
|
7
|
+
from lets_plot.plot.util import is_pandas_data_frame
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import numpy
|
|
11
|
+
except ImportError:
|
|
12
|
+
numpy = None
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
import pandas
|
|
16
|
+
except ImportError:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
import polars as pl
|
|
21
|
+
from polars.datatypes.group import INTEGER_DTYPES as PL_INTEGER_DTYPES
|
|
22
|
+
from polars.datatypes.group import FLOAT_DTYPES as PL_FLOAT_DTYPES
|
|
23
|
+
except ImportError:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
TYPE_INTEGER = 'int'
|
|
27
|
+
TYPE_FLOATING = 'float'
|
|
28
|
+
TYPE_STRING = 'str'
|
|
29
|
+
TYPE_BOOLEAN = 'bool'
|
|
30
|
+
TYPE_DATE_TIME = 'datetime'
|
|
31
|
+
TYPE_DATE = 'date' # Local date (no time zone)
|
|
32
|
+
TYPE_TIME = 'time' # Local time (we ignore time zone even if it is present)
|
|
33
|
+
TYPE_UNKNOWN = 'unknown'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _infer_type(data: Union[Dict, 'pandas.DataFrame', 'polars.DataFrame']) -> Dict[str, str]:
|
|
37
|
+
type_info = {}
|
|
38
|
+
|
|
39
|
+
if is_pandas_data_frame(data):
|
|
40
|
+
for var_name, var_content in data.items():
|
|
41
|
+
type_info[var_name] = _infer_type_pandas_dataframe(var_name, var_content)
|
|
42
|
+
elif is_polars_dataframe(data):
|
|
43
|
+
for var_name, var_type in data.schema.items():
|
|
44
|
+
type_info[var_name] = _infer_type_polars_dataframe(var_name, var_type)
|
|
45
|
+
elif isinstance(data, dict):
|
|
46
|
+
for var_name, var_content in data.items():
|
|
47
|
+
type_info[var_name] = _infer_type_dict(var_name, var_content)
|
|
48
|
+
|
|
49
|
+
return type_info
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _infer_type_pandas_dataframe(var_name: str, var_content) -> str:
|
|
53
|
+
if var_content.empty:
|
|
54
|
+
return TYPE_UNKNOWN
|
|
55
|
+
elif var_content.isna().all():
|
|
56
|
+
return TYPE_UNKNOWN
|
|
57
|
+
|
|
58
|
+
lp_dtype = TYPE_UNKNOWN
|
|
59
|
+
time_zone = None
|
|
60
|
+
pandas_dtype = pandas.api.types.infer_dtype(var_content.values, skipna=True)
|
|
61
|
+
|
|
62
|
+
if pandas_dtype == "categorical":
|
|
63
|
+
dtype = var_content.cat.categories.dtype
|
|
64
|
+
|
|
65
|
+
if numpy.issubdtype(dtype, numpy.integer):
|
|
66
|
+
lp_dtype = TYPE_INTEGER
|
|
67
|
+
elif numpy.issubdtype(dtype, numpy.floating):
|
|
68
|
+
lp_dtype = TYPE_FLOATING
|
|
69
|
+
elif numpy.issubdtype(dtype, numpy.object_):
|
|
70
|
+
# Check if all elements are strings
|
|
71
|
+
if all(isinstance(x, str) for x in var_content.cat.categories):
|
|
72
|
+
lp_dtype = TYPE_STRING
|
|
73
|
+
else:
|
|
74
|
+
# see https://pandas.pydata.org/docs/reference/api/pandas.api.types.infer_dtype.html
|
|
75
|
+
if pandas_dtype == 'string':
|
|
76
|
+
lp_dtype = TYPE_STRING
|
|
77
|
+
elif pandas_dtype == 'floating':
|
|
78
|
+
lp_dtype = TYPE_FLOATING
|
|
79
|
+
elif pandas_dtype == 'integer':
|
|
80
|
+
lp_dtype = TYPE_INTEGER
|
|
81
|
+
elif pandas_dtype == 'boolean':
|
|
82
|
+
lp_dtype = TYPE_BOOLEAN
|
|
83
|
+
|
|
84
|
+
elif pandas_dtype == 'datetime64' or pandas_dtype == 'datetime':
|
|
85
|
+
lp_dtype = TYPE_DATE_TIME
|
|
86
|
+
elif pandas_dtype == "date":
|
|
87
|
+
lp_dtype = TYPE_DATE
|
|
88
|
+
elif pandas_dtype == "time":
|
|
89
|
+
lp_dtype = TYPE_TIME
|
|
90
|
+
|
|
91
|
+
elif pandas_dtype == 'empty': # for columns with all None values
|
|
92
|
+
lp_dtype = TYPE_UNKNOWN
|
|
93
|
+
else:
|
|
94
|
+
lp_dtype = 'unknown(pandas:' + pandas_dtype + ')'
|
|
95
|
+
|
|
96
|
+
return lp_dtype
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _infer_type_polars_dataframe(var_name: str, var_type) -> str:
|
|
100
|
+
lp_dtype = TYPE_UNKNOWN
|
|
101
|
+
|
|
102
|
+
# https://docs.pola.rs/api/python/stable/reference/datatypes.html
|
|
103
|
+
if isinstance(var_type, pl.datatypes.Enum):
|
|
104
|
+
# In the current version of Polars, Enum is always a string
|
|
105
|
+
# https://docs.pola.rs/api/python/stable/reference/datatypes.html#string
|
|
106
|
+
return TYPE_STRING
|
|
107
|
+
elif isinstance(var_type, pl.datatypes.Categorical):
|
|
108
|
+
return TYPE_STRING
|
|
109
|
+
elif var_type in PL_FLOAT_DTYPES:
|
|
110
|
+
lp_dtype = TYPE_FLOATING
|
|
111
|
+
elif var_type in PL_INTEGER_DTYPES:
|
|
112
|
+
lp_dtype = TYPE_INTEGER
|
|
113
|
+
elif var_type == pl.datatypes.String:
|
|
114
|
+
lp_dtype = TYPE_STRING
|
|
115
|
+
elif var_type == pl.datatypes.Boolean:
|
|
116
|
+
lp_dtype = TYPE_BOOLEAN
|
|
117
|
+
|
|
118
|
+
elif var_type == pl.datatypes.Datetime:
|
|
119
|
+
lp_dtype = TYPE_DATE_TIME
|
|
120
|
+
elif var_type == pl.datatypes.Date:
|
|
121
|
+
lp_dtype = TYPE_DATE
|
|
122
|
+
elif var_type == pl.datatypes.Time:
|
|
123
|
+
lp_dtype = TYPE_TIME
|
|
124
|
+
|
|
125
|
+
else:
|
|
126
|
+
lp_dtype = 'unknown(polars:' + str(var_type) + ')'
|
|
127
|
+
|
|
128
|
+
return lp_dtype
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _infer_type_dict(var_name: str, var_content) -> str:
|
|
132
|
+
if isinstance(var_content, Iterable):
|
|
133
|
+
if not any(True for _ in var_content): # empty
|
|
134
|
+
return TYPE_UNKNOWN
|
|
135
|
+
else:
|
|
136
|
+
return TYPE_UNKNOWN
|
|
137
|
+
|
|
138
|
+
type_set = set(type(val) for val in var_content)
|
|
139
|
+
if type(None) in type_set:
|
|
140
|
+
type_set.remove(type(None))
|
|
141
|
+
|
|
142
|
+
if len(type_set) == 0:
|
|
143
|
+
return TYPE_UNKNOWN
|
|
144
|
+
|
|
145
|
+
if len(type_set) > 1:
|
|
146
|
+
if all(issubclass(type_obj, int) or issubclass(type_obj, float) for type_obj in type_set):
|
|
147
|
+
return TYPE_FLOATING
|
|
148
|
+
else:
|
|
149
|
+
return 'unknown(mixed types)'
|
|
150
|
+
|
|
151
|
+
lp_dtype = TYPE_UNKNOWN
|
|
152
|
+
type_obj = list(type_set)[0]
|
|
153
|
+
if type_obj == bool:
|
|
154
|
+
lp_dtype = TYPE_BOOLEAN
|
|
155
|
+
elif issubclass(type_obj, int):
|
|
156
|
+
lp_dtype = TYPE_INTEGER
|
|
157
|
+
elif issubclass(type_obj, float):
|
|
158
|
+
lp_dtype = TYPE_FLOATING
|
|
159
|
+
elif issubclass(type_obj, str):
|
|
160
|
+
lp_dtype = TYPE_STRING
|
|
161
|
+
|
|
162
|
+
elif issubclass(type_obj, datetime):
|
|
163
|
+
lp_dtype = TYPE_DATE_TIME
|
|
164
|
+
elif issubclass(type_obj, date) and not issubclass(type_obj, datetime):
|
|
165
|
+
lp_dtype = TYPE_DATE
|
|
166
|
+
elif issubclass(type_obj, time):
|
|
167
|
+
lp_dtype = TYPE_TIME
|
|
168
|
+
|
|
169
|
+
elif numpy and issubclass(type_obj, numpy.datetime64):
|
|
170
|
+
lp_dtype = TYPE_DATE_TIME
|
|
171
|
+
elif numpy and issubclass(type_obj, numpy.timedelta64):
|
|
172
|
+
# ToDo: time delta?
|
|
173
|
+
# lp_dtype = TYPE_DATE_TIME
|
|
174
|
+
lp_dtype = 'unknown(python:' + str(type_obj) + ')'
|
|
175
|
+
|
|
176
|
+
elif numpy and issubclass(type_obj, numpy.integer):
|
|
177
|
+
lp_dtype = TYPE_INTEGER
|
|
178
|
+
elif numpy and issubclass(type_obj, numpy.floating):
|
|
179
|
+
lp_dtype = TYPE_FLOATING
|
|
180
|
+
else:
|
|
181
|
+
lp_dtype = 'unknown(python:' + str(type_obj) + ')'
|
|
182
|
+
|
|
183
|
+
return lp_dtype
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _detect_time_zone(var_name: str, data: Union[Dict, 'pandas.DataFrame', 'polars.DataFrame']) -> Optional[str]:
|
|
187
|
+
if is_pandas_data_frame(data):
|
|
188
|
+
if var_name in data:
|
|
189
|
+
var_content = data[var_name]
|
|
190
|
+
if hasattr(var_content, 'dt') and hasattr(var_content.dt, 'tz') and var_content.dt.tz is not None:
|
|
191
|
+
return str(var_content.dt.tz)
|
|
192
|
+
elif is_polars_dataframe(data):
|
|
193
|
+
if var_name in data.columns:
|
|
194
|
+
col_dtype = data[var_name].dtype
|
|
195
|
+
if hasattr(col_dtype, 'time_zone'):
|
|
196
|
+
if col_dtype.time_zone is not None:
|
|
197
|
+
return str(col_dtype.time_zone)
|
|
198
|
+
elif isinstance(data, dict):
|
|
199
|
+
if var_name in data:
|
|
200
|
+
var_content = data[var_name]
|
|
201
|
+
if isinstance(var_content, Iterable):
|
|
202
|
+
for val in var_content:
|
|
203
|
+
if isinstance(val, datetime) and val.tzinfo is not None:
|
|
204
|
+
return str(val.tzinfo)
|
|
205
|
+
|
|
206
|
+
# NumPy datetime64 objects don't store timezone information,
|
|
207
|
+
# so we can't extract it from them.
|
|
208
|
+
|
|
209
|
+
return None
|