Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
6d62fc4
Iteration 172: Add na_ops β€” isna/notna/ffill/bfill
github-actions[bot] Apr 11, 2026
7fcf1e8
Iteration 174: Add pct_change for Series and DataFrame
github-actions[bot] Apr 11, 2026
3f8e809
Iteration 193: Add idxmin/idxmax for Series and DataFrame
github-actions[bot] Apr 11, 2026
e7b3fa8
Iteration 194: Add astype β€” dtype coercion for Series and DataFrame
github-actions[bot] Apr 11, 2026
69e2866
Iteration 195: Add replace β€” value substitution for Series and DataFrame
github-actions[bot] Apr 11, 2026
6191b50
Iteration 196: Add where/mask β€” conditional value selection for Serie…
github-actions[bot] Apr 11, 2026
c884123
Iteration 197: Add diff/shift β€” discrete difference and value shiftin…
github-actions[bot] Apr 11, 2026
98142e6
Iteration 199: Add duplicated/drop_duplicates and sample
github-actions[bot] Apr 11, 2026
395d575
Iteration 203: Add clip_advanced and apply/map
github-actions[bot] Apr 11, 2026
d5d54b5
Iteration 204: Add cut/qcut β€” binning continuous data into intervals
github-actions[bot] Apr 11, 2026
0721b75
Iteration 205: Add Interval/IntervalIndex β€” pandas interval type and …
github-actions[bot] Apr 11, 2026
63898f0
Iteration 206: Add getDummies/fromDummies β€” one-hot encoding
github-actions[bot] Apr 11, 2026
368088b
Iteration 208: Add crosstab β€” cross-tabulation of categorical factors
github-actions[bot] Apr 11, 2026
4829cda
Iteration 209: Add pivotTableFull β€” pivot_table with margins support
github-actions[bot] Apr 11, 2026
8c9adc3
Iteration 210: Add explode β€” DataFrame/Series list-cell expansion
github-actions[bot] Apr 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions playground/apply.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>tsb β€” apply / map</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 860px; margin: 2rem auto; padding: 0 1rem; background: #fafafa; color: #1a1a1a; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.2rem; margin-top: 2rem; border-bottom: 1px solid #ddd; padding-bottom: 0.3rem; }
pre { background: #f0f0f0; border-radius: 6px; padding: 1rem; overflow-x: auto; font-size: 0.85rem; }
.demo { background: #fff; border: 1px solid #e0e0e0; border-radius: 8px; padding: 1rem 1.5rem; margin: 1rem 0; }
button { margin-top: 0.5rem; padding: 0.4rem 1rem; cursor: pointer; border-radius: 4px; border: 1px solid #aaa; background: #f5f5f5; }
button:hover { background: #e8e8e8; }
output { display: block; margin-top: 0.5rem; white-space: pre; font-family: monospace; font-size: 0.85rem; color: #333; }
.label { font-weight: 600; font-size: 0.85rem; color: #555; margin-top: 0.8rem; }
textarea { width: 100%; box-sizing: border-box; font-family: monospace; font-size: 0.85rem; border: 1px solid #ccc; border-radius: 4px; padding: 0.5rem; }
.pandas-equiv { background: #fff8e1; border-left: 3px solid #f9a825; padding: 0.4rem 0.8rem; margin-top: 0.5rem; font-size: 0.8rem; border-radius: 0 4px 4px 0; }
</style>
</head>
<body>
<h1>tsb β€” <code>apply</code> / <code>map</code></h1>
<p>
Apply functions element-wise or per-column/row.
<code>applySeries</code> maps a function over each element.
<code>mapSeries</code> supports function, <code>Map</code>, or plain-object lookup.
<code>applyDataFrame</code> reduces each column or row to a scalar.
<code>applyExpandDataFrame</code> transforms each column/row into a new Series.
<code>mapDataFrame</code> applies a function element-wise across the whole DataFrame.
</p>

<h2>Core concept</h2>
<pre>// Element-wise apply on a Series
applySeries(s, (v) => Math.sqrt(v as number))

// Map via lookup table
mapSeries(s, { a: 1, b: 2, c: 3 })

// Reduce each column to a scalar
applyDataFrame(df, (col) => col.values.reduce((a, b) => a + b, 0))

// Transform each column, return a DataFrame
applyExpandDataFrame(df, (col) => new Series({ data: col.values.map(v => v * 2), index: col.index }))

// Element-wise map on a DataFrame
mapDataFrame(df, (v) => (v as number) ** 2)</pre>

<div class="pandas-equiv">
<strong>pandas equivalent:</strong><br />
<code>s.apply(func)</code> / <code>s.map(func_or_dict)</code><br />
<code>df.apply(func, axis=0)</code> / <code>df.applymap(func)</code> (now <code>df.map(func)</code>)
</div>

<!-- Demo 1: applySeries -->
<h2>Demo 1 β€” applySeries element-wise</h2>
<div class="demo">
<div class="label">Code</div>
<pre>const s = new Series({ data: [1, 4, 9, 16] });
applySeries(s, (v) => Math.sqrt(v as number)).values;
// β†’ [1, 2, 3, 4]</pre>
<button onclick="demo1()">Run</button>
<output id="out1"></output>
</div>

<!-- Demo 2: mapSeries with lookup -->
<h2>Demo 2 β€” mapSeries with object lookup</h2>
<div class="demo">
<div class="label">Code</div>
<pre>const s = new Series({ data: ["a", "b", "c", "d"] });
mapSeries(s, { a: 1, b: 2, c: 3 }).values;
// β†’ [1, 2, 3, null] ("d" not in lookup β†’ null)</pre>
<button onclick="demo2()">Run</button>
<output id="out2"></output>
</div>

<!-- Demo 3: applyDataFrame axis=0 -->
<h2>Demo 3 β€” applyDataFrame: sum of each column (axis=0)</h2>
<div class="demo">
<div class="label">Code</div>
<pre>const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [10, 20, 30] });
applyDataFrame(df, (col) =>
(col.values as number[]).reduce((acc, v) => acc + v, 0)
).values;
// β†’ [6, 60] (indexed by column names)</pre>
<button onclick="demo3()">Run</button>
<output id="out3"></output>
</div>

<!-- Demo 4: applyDataFrame axis=1 -->
<h2>Demo 4 β€” applyDataFrame: sum of each row (axis=1)</h2>
<div class="demo">
<div class="label">Code</div>
<pre>const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
applyDataFrame(df, (row) =>
(row.values as number[]).reduce((acc, v) => acc + v, 0),
{ axis: 1 }
).values;
// β†’ [5, 7, 9]</pre>
<button onclick="demo4()">Run</button>
<output id="out4"></output>
</div>

<!-- Demo 5: applyExpandDataFrame -->
<h2>Demo 5 β€” applyExpandDataFrame: double each column</h2>
<div class="demo">
<div class="label">Code</div>
<pre>const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
applyExpandDataFrame(df, (col) =>
new Series({ data: (col.values as number[]).map(v => v * 2), index: col.index })
);
// a: [2, 4, 6] b: [8, 10, 12]</pre>
<button onclick="demo5()">Run</button>
<output id="out5"></output>
</div>

<!-- Demo 6: mapDataFrame -->
<h2>Demo 6 β€” mapDataFrame: element-wise square</h2>
<div class="demo">
<div class="label">Code</div>
<pre>const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
mapDataFrame(df, (v) => (v as number) ** 2);
// a: [1, 4, 9] b: [16, 25, 36]</pre>
<button onclick="demo6()">Run</button>
<output id="out6"></output>
</div>

<script type="module">
import {
Series,
DataFrame,
applySeries,
mapSeries,
applyDataFrame,
applyExpandDataFrame,
mapDataFrame,
} from "https://esm.sh/tsb@latest";

window.demo1 = () => {
const s = new Series({ data: [1, 4, 9, 16] });
document.getElementById("out1").textContent =
JSON.stringify(applySeries(s, (v) => Math.sqrt(v)).values);
};

window.demo2 = () => {
const s = new Series({ data: ["a", "b", "c", "d"] });
document.getElementById("out2").textContent =
JSON.stringify(mapSeries(s, { a: 1, b: 2, c: 3 }).values);
};

window.demo3 = () => {
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [10, 20, 30] });
const result = applyDataFrame(df, (col) =>
col.values.reduce((acc, v) => acc + v, 0),
);
document.getElementById("out3").textContent =
`values: ${JSON.stringify(result.values)}\nindex: ${JSON.stringify([result.index.at(0), result.index.at(1)])}`;
};

window.demo4 = () => {
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
const result = applyDataFrame(
df,
(row) => row.values.reduce((acc, v) => acc + v, 0),
{ axis: 1 },
);
document.getElementById("out4").textContent = JSON.stringify(result.values);
};

window.demo5 = () => {
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
const result = applyExpandDataFrame(df, (col) =>
new Series({ data: col.values.map((v) => v * 2), index: col.index }),
);
document.getElementById("out5").textContent =
`a: ${JSON.stringify(result.col("a").values)}\nb: ${JSON.stringify(result.col("b").values)}`;
};

window.demo6 = () => {
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
const result = mapDataFrame(df, (v) => v ** 2);
document.getElementById("out6").textContent =
`a: ${JSON.stringify(result.col("a").values)}\nb: ${JSON.stringify(result.col("b").values)}`;
};
</script>
</body>
</html>
Loading