Misc helpers (overlay, compare, reindex)¶
Three sibling functions from upstream TimeSeriesEcon.jl/src/various.jl,
sharing the LikeWorkspace dispatch (Workspace / MVTSeries / Mapping):
overlay— first-valid-wins composition over TSeries / Workspace / MVTSeries values. The dtype-appropriate typenan (NaN for floats,iinfo.maxfor integers,Falsefor booleans) marks "missing"; the leftmost non-missing value wins position-by-position.compare— recursive structural / numeric comparison. Returns aCompareResult(truthy on equality;.differencescarries the per-leaf diff). Tolerance kwargs (atol/rtol/nans) match the Juliacompare/@comparesurface name-for-name.reindex— shift every MIT-keyed position inside a container so thatfrommaps toto; values are preserved. Dispatches over MIT / MITRange / TSeries / MVTSeries / Workspace.
tsecon._various ¶
Misc helpers from TimeSeriesEcon.jl's various.jl.
Three sibling functions sharing the LikeWorkspace dispatch (Workspace /
MVTSeries / :class:collections.abc.Mapping):
- :func:
overlay— first-valid-wins composition over TSeries / Workspace / MVTSeries values. NaN (and the dtype-appropriatetypenan) marks "missing"; the leftmost non-missing value wins position-by-position. - :func:
compare— recursive structural / numeric comparison. Returns a :class:CompareResult(truthy on equality;.differencescarries the per-leaf diff). Tolerance kwargs (atol/rtol/nans) and walk kwargs (ignoremissing/showequal/quiet/trange) match the Julia surface name-for-name. - :func:
reindex— shift every MIT-keyed position inside a container so thatfrommaps toto; the underlying values are preserved. Dispatches over MIT / MITRange / TSeries / MVTSeries / Workspace.
Julia's @compare macro collapses to a plain function alias here: the
macro existed only to capture the variable names for printing, and
:class:CompareResult.differences already exposes that information without
needing AST rewriting. Code that wrote @compare(v1, v2, atol=1e-5)
ports to compare(v1, v2, atol=1e-5) — the Python idiom of returning a
structured diff matches the Julia behaviour for both interactive (print(result))
and programmatic (result.differences) use.
Remaining pieces of various.jl are deferred:
@showall— Julia macro for non-truncating display; Python usesprint(repr(x))directly (the truncation lives in our__repr__, not in a separate IO context).clean_old_frequencies— Julia v0.4→v0.5 frequency-sanitiser; not applicable to tsecon's cached-singleton frequency model. Tracked as parity gap G14.TOML.printoverloads — left to v1.0 if the JSON round-trip (io/json.py) doesn't cover the use case.is_yearly/is_quarterly/ etc. — already ported in :mod:tsecon.frequencieswith PEP-8 underscore naming.
CompareDifference
dataclass
¶
One line of the recursive diff produced by :func:compare.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
tuple[str, ...]
|
Hierarchical tuple of names, e.g. |
message |
str
|
Short human-readable description: |
Source code in src/tsecon/_various.py
CompareResult
dataclass
¶
The structured return value of :func:compare.
Truthy iff the two inputs compared as equal — use
if compare(a, b): ... for the Julia-style one-line check.
str(result) reproduces the printed diff (one line per
:class:CompareDifference). .differences exposes the diff
programmatically.
Source code in src/tsecon/_various.py
overlay ¶
Return the first non-missing value, position-by-position, from left to right.
"Missing" is defined by the dtype-appropriate typenan (NaN for
floats, iinfo(dtype).max for integers, False for booleans).
The dispatch is on the argument types — all arguments must agree on a
container family for the recursive form to apply:
- All :class:
~tsecon.tseries.TSeries— build a new TSeries over eitherrng=(when given) or the union of all input ranges (rangeof_span(*args)). For each position, the leftmost input that has a non-typenan value at that position wins. The output dtype is the NumPy promotion of all input dtypes. - All :class:
~tsecon.mvtseries.MVTSeries— return an MVTSeries over the union range and the ordered union of column names; each column is the overlay of the corresponding TSeries columns. - All Workspace / MVTSeries / Mapping — return a
:class:
~tsecon.workspace.Workspace. For each key present in any input, collect the values across inputs that have it and recurse; the recursive call may dispatch back into the TSeries / Workspace / MVTSeries / scalar paths. - Mixed types (e.g. a TSeries and a scalar) — fall through to the scalar walk: return the leftmost non-typenan value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
One or more values to overlay. At least one is required. |
()
|
rng
|
MITRange | None
|
Optional :class: |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A TSeries / MVTSeries / Workspace / scalar matching the input family. |
Raises:
| Type | Description |
|---|---|
TypeError
|
On empty argument list, on mixed-frequency inputs, or on
|
Source code in src/tsecon/_various.py
compare ¶
compare(
x: Any,
y: Any,
*,
name: str = "_",
showequal: bool = False,
ignoremissing: bool = False,
quiet: bool = False,
left: str = "left",
right: str = "right",
atol: float = 0.0,
rtol: float | None = None,
nans: bool = False,
trange: MITRange | None = None,
) -> CompareResult
Recursively compare x and y, returning a :class:CompareResult.
The walk dispatches over:
- :class:
~tsecon.workspace.Workspace, :class:~tsecon.mvtseries.MVTSeries, and :class:collections.abc.Mapping— treated as name-keyed containers and recursed key-by-key. Missing keys produce"missing in <left|right>"lines (unlessignoremissing=True). - :class:
~tsecon.tseries.TSeries— compared range-by-range using :func:numpy.allclosewith the givenatol/rtol/nans. Mismatched ranges count as different (unlessignoremissing=True, in which case the intersection is compared). - NumPy arrays of numbers — compared by shape + element-wise
:func:
numpy.allclose. - NumPy arrays of other dtypes — walked element-by-element.
- Scalars — compared via :func:
numpy.isclose. - Everything else — compared with
==.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Any
|
The two values to compare. |
required |
y
|
Any
|
The two values to compare. |
required |
name
|
str
|
Top-level name in the printed/structured diff ( |
'_'
|
showequal
|
bool
|
When True, also emit |
False
|
ignoremissing
|
bool
|
When True, ignore keys present in one side but not the other
(they don't print and don't affect |
False
|
quiet
|
bool
|
When True, suppress printing to stdout. The :class: |
False
|
left
|
str
|
Names used in |
'left'
|
right
|
str
|
Names used in |
'left'
|
atol
|
float
|
Tolerances forwarded to :func: |
0.0
|
rtol
|
float
|
Tolerances forwarded to :func: |
0.0
|
nans
|
float
|
Tolerances forwarded to :func: |
0.0
|
trange
|
MITRange | None
|
Optional :class: |
None
|
Returns:
| Type | Description |
|---|---|
CompareResult
|
Truthy iff |
Notes
Julia's accompanying @compare macro folds into this same
function. The macro existed only to capture the input variable names
for printing; Python callers can pass left= and right= if
they want the same labelling.
Source code in src/tsecon/_various.py
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | |
reindex ¶
Shift every MIT-keyed position so that old maps to new.
old_to_new is a 2-tuple (old_mit, new_mit). In MIT-value
space, every output position is the input position plus
new_mit.value - old_mit.value, and the result carries
new_mit.frequency as its frequency label.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Any
|
The value to reindex. Supported types:
|
required |
old_to_new
|
tuple[MIT, MIT]
|
Pair |
required |
copy
|
bool
|
When True, force an independent values buffer for the returned
:class: |
False
|
Returns:
| Type | Description |
|---|---|
The same kind of object as ``x``, with the MIT label shifted.
|
|
Raises:
| Type | Description |
|---|---|
TypeError
|
On a malformed |
Examples:
Re-anchor a quarterly TSeries from a 2021Q1 origin to a Unit 1-based origin::
>>> from tsecon import TSeries, qq, period, Unit, reindex
>>> ts = TSeries(qq(2021, 1), [1.0, 2.0, 3.0])
>>> reindex(ts, (qq(2021, 1), period(Unit(), 1))).firstdate
1U
Source code in src/tsecon/_various.py
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | |