dycw-utilities 0.159.3__py3-none-any.whl → 0.159.4__py3-none-any.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.159.3
3
+ Version: 0.159.4
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=VdqkGeeq4rCnCdHuCDKZa_vNmpgPYng4SgWvMihfJwo,60
1
+ utilities/__init__.py,sha256=8PwC9PN_0tTaC-HGuAmY0sqVwC7bKnFBwSDdjEvRwnk,60
2
2
  utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
3
3
  utilities/asyncio.py,sha256=PUedzQ5deqlSECQ33sam9cRzI9TnygHz3FdOqWJWPTM,15288
4
4
  utilities/atomicwrites.py,sha256=tPo6r-Rypd9u99u66B9z86YBPpnLrlHtwox_8Z7T34Y,5790
@@ -32,7 +32,7 @@ utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
32
32
  utilities/libcst.py,sha256=TKgKN4bNmtBNEE-TUfhTyd1BrTncfsl_7tTuhpesGYY,5585
33
33
  utilities/lightweight_charts.py,sha256=YM3ojBvJxuCSUBu_KrhFBmaMCvRPvupKC3qkm-UVZq4,2751
34
34
  utilities/logging.py,sha256=ihbfQJgjc7t3Pds0oPvF_J1eigiqFKzxNOijzoee8U4,18064
35
- utilities/math.py,sha256=7ve4RxX3g-FGGVnWV0K9bBeGnKUEjnTbH13VxdvFtGE,26847
35
+ utilities/math.py,sha256=cevB-YyEYAzJTWtkAr7qeeu-hbxorDI3gMznXlmNQkw,26897
36
36
  utilities/memory_profiler.py,sha256=XzN56jDCa5aqXS_DxEjb_K4L6aIWh_5zyKi6OhcIxw0,853
37
37
  utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
38
38
  utilities/more_itertools.py,sha256=syfIPhQF_WS-YiicdGe2h5F1G-Ld12Q2XsVduL2hA40,10908
@@ -45,7 +45,7 @@ utilities/parse.py,sha256=JcJn5yXKhIWXBCwgBdPsyu7Hvcuw6kyEdqvaebCaI9k,17951
45
45
  utilities/pathlib.py,sha256=qGuU8XPmdgGpy8tOMUgelfXx3kxI8h9IaV3TI_06QGE,8428
46
46
  utilities/pickle.py,sha256=MBT2xZCsv0pH868IXLGKnlcqNx2IRVKYNpRcqiQQqxw,653
47
47
  utilities/platform.py,sha256=pTn7gw6N4T6LdKrf0virwarof_mze9WtoQlrGMzhGVI,2798
48
- utilities/polars.py,sha256=_pQS5wmtkMgu5CZZKDVA4AnT6NyLSlYKe5GK6hBR7vU,77876
48
+ utilities/polars.py,sha256=4Qc9lv0SZEpjXFKANUQBb7nA55sC4zaHtlZEJXTBALg,76896
49
49
  utilities/polars_ols.py,sha256=Uc9V5kvlWZ5cU93lKZ-cfAKdVFFw81tqwLW9PxtUvMs,5618
50
50
  utilities/postgres.py,sha256=ynCTTaF-bVEOSW-KEAR-dlLh_hYjeVVjm__-4pEU8Zk,12269
51
51
  utilities/pottery.py,sha256=ggMN72Y7wx7Js8VN6eyNyodpm8TIYqZHGghkDPXIVWk,3949
@@ -87,8 +87,8 @@ utilities/zoneinfo.py,sha256=FBMcUQ4662Aq8SsuCL1OAhDQiyANmVjtb-C30DRrWoE,1966
87
87
  utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
88
88
  utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
89
89
  utilities/pytest_plugins/pytest_regressions.py,sha256=9v8kAXDM2ycIXJBimoiF4EgrwbUvxTycFWJiGR_GHhM,1466
90
- dycw_utilities-0.159.3.dist-info/METADATA,sha256=vx1O7lyZWHV89NyvhKldxK9kl_d9wpawar1WayIcveA,1643
91
- dycw_utilities-0.159.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- dycw_utilities-0.159.3.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
93
- dycw_utilities-0.159.3.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
- dycw_utilities-0.159.3.dist-info/RECORD,,
90
+ dycw_utilities-0.159.4.dist-info/METADATA,sha256=WLxPLavB-QLjzJhQr7T5-LbVJNRA_PlRiBtCJTT9FmQ,1643
91
+ dycw_utilities-0.159.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ dycw_utilities-0.159.4.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
93
+ dycw_utilities-0.159.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
+ dycw_utilities-0.159.4.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.159.3"
3
+ __version__ = "0.159.4"
utilities/math.py CHANGED
@@ -641,7 +641,10 @@ def _is_close(
641
641
  ##
642
642
 
643
643
 
644
- def number_of_decimals(x: float, /, *, max_decimals: int = 20) -> int:
644
+ MAX_DECIMALS = 10
645
+
646
+
647
+ def number_of_decimals(x: float, /, *, max_decimals: int = MAX_DECIMALS) -> int:
645
648
  """Get the number of decimals."""
646
649
  _, frac = divmod(x, 1)
647
650
  results = (
@@ -889,6 +892,7 @@ def significant_figures(x: float, /, *, n: int = 2) -> str:
889
892
 
890
893
 
891
894
  __all__ = [
895
+ "MAX_DECIMALS",
892
896
  "MAX_FLOAT32",
893
897
  "MAX_FLOAT64",
894
898
  "MAX_INT8",
utilities/polars.py CHANGED
@@ -53,11 +53,10 @@ from polars.schema import Schema
53
53
  from polars.testing import assert_frame_equal, assert_series_equal
54
54
  from whenever import DateDelta, DateTimeDelta, PlainDateTime, TimeDelta, ZonedDateTime
55
55
 
56
+ import utilities.math
56
57
  from utilities.dataclasses import yield_fields
57
58
  from utilities.errors import ImpossibleCaseError
58
59
  from utilities.functions import (
59
- EnsureIntError,
60
- ensure_int,
61
60
  is_dataclass_class,
62
61
  is_dataclass_instance,
63
62
  make_isinstance,
@@ -80,12 +79,12 @@ from utilities.iterables import (
80
79
  )
81
80
  from utilities.json import write_formatted_json
82
81
  from utilities.math import (
82
+ MAX_DECIMALS,
83
83
  CheckIntegerError,
84
84
  check_integer,
85
85
  ewm_parameters,
86
86
  is_less_than,
87
87
  is_non_negative,
88
- number_of_decimals,
89
88
  )
90
89
  from utilities.reprlib import get_repr
91
90
  from utilities.types import MaybeStr, Number, PathLike, WeekDay
@@ -1427,56 +1426,6 @@ def get_frequency_spectrum(series: Series, /, *, d: int = 1) -> DataFrame:
1427
1426
  ##
1428
1427
 
1429
1428
 
1430
- @overload
1431
- def get_series_number_of_decimals(
1432
- series: Series, /, *, nullable: Literal[True]
1433
- ) -> int | None: ...
1434
- @overload
1435
- def get_series_number_of_decimals(
1436
- series: Series, /, *, nullable: Literal[False] = False
1437
- ) -> int: ...
1438
- @overload
1439
- def get_series_number_of_decimals(
1440
- series: Series, /, *, nullable: bool = False
1441
- ) -> int | None: ...
1442
- def get_series_number_of_decimals(
1443
- series: Series, /, *, nullable: bool = False
1444
- ) -> int | None:
1445
- """Get the number of decimals of a series."""
1446
- if not isinstance(dtype := series.dtype, Float64):
1447
- raise _GetSeriesNumberOfDecimalsNotFloatError(dtype=dtype)
1448
- decimals = series.map_elements(number_of_decimals, return_dtype=Int64).max()
1449
- try:
1450
- return ensure_int(decimals, nullable=nullable)
1451
- except EnsureIntError:
1452
- raise _GetSeriesNumberOfDecimalsAllNullError(series=series) from None
1453
-
1454
-
1455
- @dataclass(kw_only=True, slots=True)
1456
- class GetSeriesNumberOfDecimalsError(Exception): ...
1457
-
1458
-
1459
- @dataclass(kw_only=True, slots=True)
1460
- class _GetSeriesNumberOfDecimalsNotFloatError(GetSeriesNumberOfDecimalsError):
1461
- dtype: DataType
1462
-
1463
- @override
1464
- def __str__(self) -> str:
1465
- return f"Data type must be Float64; got {self.dtype}"
1466
-
1467
-
1468
- @dataclass(kw_only=True, slots=True)
1469
- class _GetSeriesNumberOfDecimalsAllNullError(GetSeriesNumberOfDecimalsError):
1470
- series: Series
1471
-
1472
- @override
1473
- def __str__(self) -> str:
1474
- return f"Series must not be all-null; got {self.series}"
1475
-
1476
-
1477
- ##
1478
-
1479
-
1480
1429
  @overload
1481
1430
  def increasing_horizontal(*columns: ExprLike) -> Expr: ...
1482
1431
  @overload
@@ -2023,6 +1972,26 @@ def normal(
2023
1972
  ##
2024
1973
 
2025
1974
 
1975
+ def number_of_decimals(
1976
+ series: Series, /, *, max_decimals: int = MAX_DECIMALS
1977
+ ) -> Series:
1978
+ """Get the number of decimals."""
1979
+ frac = series - series.floor()
1980
+ results = [
1981
+ _number_of_decimals_check_scale(frac, s) for s in range(max_decimals + 1)
1982
+ ]
1983
+ df_results = concat_series(*results)
1984
+ return first_true_horizontal(df_results)
1985
+
1986
+
1987
+ def _number_of_decimals_check_scale(frac: Series, scale: int, /) -> Series:
1988
+ scaled = 10**scale * frac
1989
+ return is_close(scaled, scaled.round()).alias(str(scale))
1990
+
1991
+
1992
+ ##
1993
+
1994
+
2026
1995
  def offset_datetime(
2027
1996
  datetime: ZonedDateTime, offset: str, /, *, n: int = 1
2028
1997
  ) -> ZonedDateTime:
@@ -2389,7 +2358,7 @@ def round_to_float(
2389
2358
  """Round a column to the nearest multiple of another float."""
2390
2359
  x = ensure_expr_or_series(x)
2391
2360
  z = (x / y).round(mode=mode) * y
2392
- return z.round(decimals=number_of_decimals(y) + 1)
2361
+ return z.round(decimals=utilities.math.number_of_decimals(y) + 1)
2393
2362
 
2394
2363
 
2395
2364
  ##
@@ -2595,7 +2564,6 @@ __all__ = [
2595
2564
  "ExprOrSeries",
2596
2565
  "FiniteEWMMeanError",
2597
2566
  "GetDataTypeOrSeriesTimeZoneError",
2598
- "GetSeriesNumberOfDecimalsError",
2599
2567
  "InsertAfterError",
2600
2568
  "InsertBeforeError",
2601
2569
  "InsertBetweenError",
@@ -2634,7 +2602,6 @@ __all__ = [
2634
2602
  "get_data_type_or_series_time_zone",
2635
2603
  "get_expr_name",
2636
2604
  "get_frequency_spectrum",
2637
- "get_series_number_of_decimals",
2638
2605
  "increasing_horizontal",
2639
2606
  "insert_after",
2640
2607
  "insert_before",
@@ -2650,6 +2617,7 @@ __all__ = [
2650
2617
  "nan_sum_agg",
2651
2618
  "nan_sum_cols",
2652
2619
  "normal",
2620
+ "number_of_decimals",
2653
2621
  "offset_datetime",
2654
2622
  "one_column",
2655
2623
  "order_of_magnitude",