Skip to content

Commit e30e6a4

Browse files
authored
Merge pull request #174 from githubnext/autoloop/build-tsb-pandas-typescript-migration
[Autoloop] Add timedelta_range (pandas feature port)
2 parents 5aec3dc + 9746c2e commit e30e6a4

102 files changed

Lines changed: 21615 additions & 218 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

playground/at_iat.html

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>at_iat — tsb playground</title>
7+
<style>
8+
body { font-family: system-ui, sans-serif; max-width: 860px; margin: 2rem auto; padding: 0 1rem; }
9+
h1 { font-size: 1.6rem; }
10+
h2 { font-size: 1.2rem; margin-top: 2rem; }
11+
pre { background: #f6f8fa; border-radius: 6px; padding: 1rem; overflow-x: auto; }
12+
code { font-family: monospace; }
13+
.label { color: #555; font-size: 0.85rem; }
14+
.back { display: inline-block; margin-bottom: 1rem; color: #0969da; text-decoration: none; }
15+
.back:hover { text-decoration: underline; }
16+
</style>
17+
</head>
18+
<body>
19+
<a class="back" href="index.html">← Back to playground index</a>
20+
<h1>at_iat — fast scalar access for Series and DataFrame</h1>
21+
<p>
22+
Fast single-cell accessors that mirror the pandas <code>.at</code> and <code>.iat</code>
23+
indexers. Use these when you need a single scalar value — they are clearer and faster
24+
than <code>.loc</code> / <code>.iloc</code> for single-element access.
25+
</p>
26+
27+
<h2>seriesAt — access by label</h2>
28+
<p class="label">Python pandas equivalent:</p>
29+
<pre><code>import pandas as pd
30+
s = pd.Series([10, 20, 30], index=["a", "b", "c"])
31+
s.at["b"] # 20
32+
</code></pre>
33+
<p class="label">tsb equivalent:</p>
34+
<pre><code>import { Series, seriesAt } from "tsb";
35+
36+
const s = new Series({ data: [10, 20, 30], index: ["a", "b", "c"] });
37+
seriesAt(s, "b"); // 20
38+
seriesAt(s, "a"); // 10
39+
</code></pre>
40+
41+
<h2>seriesIat — access by integer position</h2>
42+
<p class="label">Python pandas equivalent:</p>
43+
<pre><code>s.iat[2] # 30
44+
s.iat[-1] # 30 (negative indexing)
45+
</code></pre>
46+
<p class="label">tsb equivalent:</p>
47+
<pre><code>import { seriesIat } from "tsb";
48+
49+
seriesIat(s, 2); // 30
50+
seriesIat(s, -1); // 30
51+
</code></pre>
52+
53+
<h2>dataFrameAt — access by row label and column name</h2>
54+
<p class="label">Python pandas equivalent:</p>
55+
<pre><code>df = pd.DataFrame({"x": [1, 2], "y": [3, 4]}, index=["r0", "r1"])
56+
df.at["r1", "x"] # 2
57+
</code></pre>
58+
<p class="label">tsb equivalent:</p>
59+
<pre><code>import { DataFrame, dataFrameAt } from "tsb";
60+
61+
const df = DataFrame.fromColumns(
62+
{ x: [1, 2], y: [3, 4] },
63+
{ index: ["r0", "r1"] },
64+
);
65+
dataFrameAt(df, "r1", "x"); // 2
66+
dataFrameAt(df, "r0", "y"); // 3
67+
</code></pre>
68+
69+
<h2>dataFrameIat — access by integer row and column position</h2>
70+
<p class="label">Python pandas equivalent:</p>
71+
<pre><code>df.iat[0, 1] # 3 (row 0, col 1 = "y")
72+
df.iat[1, -1] # 4 (last col)
73+
</code></pre>
74+
<p class="label">tsb equivalent:</p>
75+
<pre><code>import { dataFrameIat } from "tsb";
76+
77+
dataFrameIat(df, 0, 1); // 3 (row 0, column index 1 = "y")
78+
dataFrameIat(df, 1, -1); // 4 (last column, row 1)
79+
</code></pre>
80+
81+
<h2>Summary</h2>
82+
<pre><code>// seriesAt(s, label) — label-based scalar access
83+
// seriesIat(s, i) — position-based scalar access
84+
// dataFrameAt(df, rowLabel, col) — label × label scalar access
85+
// dataFrameIat(df, rowInt, col) — position × position scalar access
86+
</code></pre>
87+
</body>
88+
</html>

playground/between.html

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>between — tsb playground</title>
7+
<style>
8+
body { font-family: system-ui, sans-serif; max-width: 860px; margin: 2rem auto; padding: 0 1rem; }
9+
h1 { font-size: 1.6rem; }
10+
h2 { font-size: 1.2rem; margin-top: 2rem; }
11+
pre { background: #f6f8fa; border-radius: 6px; padding: 1rem; overflow-x: auto; }
12+
code { font-family: monospace; }
13+
.label { color: #555; font-size: 0.85rem; }
14+
.back { display: inline-block; margin-bottom: 1rem; color: #0969da; text-decoration: none; }
15+
.back:hover { text-decoration: underline; }
16+
</style>
17+
</head>
18+
<body>
19+
<a class="back" href="index.html">← Back to playground index</a>
20+
<h1>between</h1>
21+
<p>
22+
Element-wise range check: returns a boolean Series indicating whether each value lies
23+
within <code>[left, right]</code>. Mirrors <code>pandas.Series.between</code>.
24+
</p>
25+
26+
<h2>seriesBetween — inclusive="both" (default)</h2>
27+
<p class="label">Python pandas equivalent:</p>
28+
<pre><code>import pandas as pd
29+
30+
s = pd.Series([1, 2, 3, 4, 5])
31+
print(s.between(2, 4))
32+
# 0 False
33+
# 1 True
34+
# 2 True
35+
# 3 True
36+
# 4 False
37+
# dtype: bool
38+
</code></pre>
39+
<p class="label">tsb equivalent:</p>
40+
<pre><code>import { Series, seriesBetween } from "tsb";
41+
42+
const s = new Series({ data: [1, 2, 3, 4, 5] });
43+
seriesBetween(s, 2, 4).values;
44+
// [false, true, true, true, false]
45+
</code></pre>
46+
47+
<h2>Inclusive options</h2>
48+
<p class="label">Python pandas equivalent:</p>
49+
<pre><code>import pandas as pd
50+
51+
s = pd.Series([1, 2, 3, 4, 5])
52+
53+
s.between(2, 4, inclusive="left").tolist()
54+
# [False, True, True, False, False]
55+
56+
s.between(2, 4, inclusive="right").tolist()
57+
# [False, False, True, True, False]
58+
59+
s.between(2, 4, inclusive="neither").tolist()
60+
# [False, False, True, False, False]
61+
</code></pre>
62+
<p class="label">tsb equivalent:</p>
63+
<pre><code>import { Series, seriesBetween } from "tsb";
64+
65+
const s = new Series({ data: [1, 2, 3, 4, 5] });
66+
67+
seriesBetween(s, 2, 4, { inclusive: "left" }).values;
68+
// [false, true, true, false, false]
69+
70+
seriesBetween(s, 2, 4, { inclusive: "right" }).values;
71+
// [false, false, true, true, false]
72+
73+
seriesBetween(s, 2, 4, { inclusive: "neither" }).values;
74+
// [false, false, true, false, false]
75+
</code></pre>
76+
77+
<h2>Missing values</h2>
78+
<p class="label">Python pandas equivalent:</p>
79+
<pre><code>import pandas as pd
80+
import numpy as np
81+
82+
s = pd.Series([1, None, np.nan, 4])
83+
s.between(0, 5).tolist()
84+
# [True, False, False, True]
85+
</code></pre>
86+
<p class="label">tsb equivalent:</p>
87+
<pre><code>import { Series, seriesBetween } from "tsb";
88+
89+
const s = new Series({ data: [1, null, NaN, 4] });
90+
seriesBetween(s, 0, 5).values;
91+
// [true, false, false, true]
92+
</code></pre>
93+
94+
<h2>String comparison</h2>
95+
<p class="label">Python pandas equivalent:</p>
96+
<pre><code>import pandas as pd
97+
98+
s = pd.Series(["apple", "banana", "cherry", "date"])
99+
s.between("banana", "cherry").tolist()
100+
# [False, True, True, False]
101+
</code></pre>
102+
<p class="label">tsb equivalent:</p>
103+
<pre><code>import { Series, seriesBetween } from "tsb";
104+
105+
const s = new Series({ data: ["apple", "banana", "cherry", "date"] });
106+
seriesBetween(s, "banana", "cherry").values;
107+
// [false, true, true, false]
108+
</code></pre>
109+
</body>
110+
</html>

playground/combine.html

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>combine — Element-wise Combination — tsb playground</title>
7+
<style>
8+
body { font-family: system-ui, sans-serif; max-width: 900px; margin: 2rem auto; padding: 0 1rem; }
9+
h1 { color: #1a56db; }
10+
pre { background: #f4f4f4; padding: 1rem; border-radius: 6px; overflow-x: auto; }
11+
.output { background: #e8f5e9; padding: 1rem; border-radius: 6px; white-space: pre; font-family: monospace; min-height: 4rem; }
12+
button { background: #1a56db; color: white; border: none; padding: 0.5rem 1.2rem; border-radius: 4px; cursor: pointer; margin: 0.2rem; }
13+
button:hover { background: #1345b3; }
14+
</style>
15+
</head>
16+
<body>
17+
<h1>combine — Element-wise Combination</h1>
18+
<p>
19+
<code>combineSeries(a, b, func)</code> and <code>combineDataFrame(a, b, func)</code>
20+
combine two objects element-wise using a caller-supplied binary function.
21+
The result index is the <strong>union</strong> of both indices; a
22+
<code>fillValue</code> (default <code>null</code>) is used when only one
23+
side has a value for a given label.
24+
</p>
25+
26+
<h2>Interactive Demo</h2>
27+
<button onclick="runSeriesMax()">Series: max</button>
28+
<button onclick="runSeriesUnion()">Series: union index</button>
29+
<button onclick="runDfShared()">DataFrame: shared columns</button>
30+
<button onclick="runDfUnion()">DataFrame: union columns</button>
31+
<div class="output" id="output">Click a button above to run an example.</div>
32+
33+
<h2>Code Examples</h2>
34+
<pre><code>import { Series, DataFrame, combineSeries, combineDataFrame } from "tsb";
35+
36+
// ── Series ──────────────────────────────────────────────────────────────────
37+
const a = new Series({ data: [1, 5, 3], index: [0, 1, 2] });
38+
const b = new Series({ data: [10, 2, 30], index: [0, 1, 2] });
39+
40+
// Element-wise max
41+
combineSeries(a, b, (x, y) => Math.max(x, y)).values; // [10, 5, 30]
42+
43+
// Union index with fillValue=0
44+
const c = new Series({ data: [1, 2], index: ["x", "y"] });
45+
const d = new Series({ data: [10, 30], index: ["x", "z"] });
46+
combineSeries(c, d, (x, y) => (x ?? 0) + (y ?? 0), 0).values;
47+
// x:11, y:2, z:30
48+
49+
// ── DataFrame ───────────────────────────────────────────────────────────────
50+
const df1 = DataFrame.fromColumns({ a: [1, 5], b: [100, 200] });
51+
const df2 = DataFrame.fromColumns({ a: [10, 2], c: [1000, 2000] });
52+
53+
// Shared column "a": element-wise min; unshared columns processed with fillValue
54+
combineDataFrame(df1, df2, (p, q) => Math.min(p ?? Infinity, q ?? Infinity));
55+
56+
// overwrite: false — unshared columns preserved as-is
57+
combineDataFrame(df1, df2, (p, q) => Math.min(p ?? Infinity, q ?? Infinity),
58+
{ overwrite: false });
59+
</code></pre>
60+
61+
<script type="module">
62+
const mod = await import("../src/index.ts").catch(() => null);
63+
64+
function display(label, text) {
65+
document.getElementById("output").textContent = label + "\n\n" + text;
66+
}
67+
68+
window.runSeriesMax = function () {
69+
if (!mod) { display("", "(Module unavailable — run via bun)"); return; }
70+
const { Series, combineSeries } = mod;
71+
const a = new Series({ data: [1, 5, 3], index: [0, 1, 2] });
72+
const b = new Series({ data: [10, 2, 30], index: [0, 1, 2] });
73+
const result = combineSeries(a, b, (x, y) => Math.max(x, y));
74+
display("combineSeries(a, b, Math.max):", String(result));
75+
};
76+
77+
window.runSeriesUnion = function () {
78+
if (!mod) { display("", "(Module unavailable — run via bun)"); return; }
79+
const { Series, combineSeries } = mod;
80+
const c = new Series({ data: [1, 2], index: ["x", "y"] });
81+
const d = new Series({ data: [10, 30], index: ["x", "z"] });
82+
const result = combineSeries(c, d, (x, y) => (x ?? 0) + (y ?? 0), 0);
83+
display("combineSeries with union index (fillValue=0):", String(result));
84+
};
85+
86+
window.runDfShared = function () {
87+
if (!mod) { display("", "(Module unavailable — run via bun)"); return; }
88+
const { DataFrame, combineDataFrame } = mod;
89+
const df1 = DataFrame.fromColumns({ a: [1, 5, 3], b: [100, 200, 300] });
90+
const df2 = DataFrame.fromColumns({ a: [10, 2, 30], b: [50, 250, 150] });
91+
const result = combineDataFrame(df1, df2, (p, q) => Math.max(p, q));
92+
display("combineDataFrame(df1, df2, Math.max) — shared columns:", String(result));
93+
};
94+
95+
window.runDfUnion = function () {
96+
if (!mod) { display("", "(Module unavailable — run via bun)"); return; }
97+
const { DataFrame, combineDataFrame } = mod;
98+
const df1 = DataFrame.fromColumns({ a: [1, 2], b: [10, 20] });
99+
const df2 = DataFrame.fromColumns({ a: [100, 200], c: [1000, 2000] });
100+
const result = combineDataFrame(df1, df2, (p, q) => {
101+
if (p === null) return q;
102+
if (q === null) return p;
103+
return Math.min(p, q);
104+
}, { overwrite: false });
105+
display("combineDataFrame — union columns, overwrite=false:", String(result));
106+
};
107+
</script>
108+
</body>
109+
</html>

0 commit comments

Comments
 (0)