Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0ad6935
Initial plan
Copilot Apr 8, 2026
fa0422b
Rewrite value_counts.html to use interactive playground format
Copilot Apr 8, 2026
7403135
Rewrite cat_accessor playground to interactive dark-theme format
Copilot Apr 8, 2026
a5f0b03
Rewrite cum_ops.html to use interactive playground format
Copilot Apr 8, 2026
64f9464
Rewrite elem_ops.html to use interactive playground format
Copilot Apr 8, 2026
b54bbf6
Rewrite melt.html playground to interactive dark-theme format
Copilot Apr 8, 2026
1100176
Rewrite multi_index.html to interactive playground format
Copilot Apr 8, 2026
a686108
Rewrite nlargest.html to use interactive playground format
Copilot Apr 8, 2026
998d5bc
Rewrite pivot.html to use interactive playground format
Copilot Apr 8, 2026
b3a94e2
Rewrite playground/rank.html to use interactive playground format
Copilot Apr 8, 2026
92b8f56
Rewrite rolling.html to interactive playground format
Copilot Apr 8, 2026
0f786c0
Rewrite stack_unstack playground to interactive dark-theme format
Copilot Apr 8, 2026
b156b97
Rewrite playground/ewm.html to interactive playground format
Copilot Apr 8, 2026
ab8565d
Rewrite datetime_accessor playground to interactive template format
Copilot Apr 8, 2026
bb65a48
Rewrite playground/csv.html to use proper interactive playground format
Copilot Apr 8, 2026
698b6b6
Rewrite playground/json.html to use interactive playground template f…
Copilot Apr 8, 2026
f4ea0f6
Fix playground inconsistencies: update index.html links, convert brok…
Copilot Apr 8, 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
474 changes: 367 additions & 107 deletions playground/cat_accessor.html

Large diffs are not rendered by default.

512 changes: 376 additions & 136 deletions playground/csv.html

Large diffs are not rendered by default.

502 changes: 375 additions & 127 deletions playground/cum_ops.html

Large diffs are not rendered by default.

600 changes: 402 additions & 198 deletions playground/datetime_accessor.html

Large diffs are not rendered by default.

515 changes: 379 additions & 136 deletions playground/describe.html

Large diffs are not rendered by default.

500 changes: 366 additions & 134 deletions playground/elem_ops.html

Large diffs are not rendered by default.

764 changes: 479 additions & 285 deletions playground/ewm.html

Large diffs are not rendered by default.

102 changes: 51 additions & 51 deletions playground/index.html

Large diffs are not rendered by default.

515 changes: 376 additions & 139 deletions playground/json.html

Large diffs are not rendered by default.

344 changes: 275 additions & 69 deletions playground/melt.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,200 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>tsb — melt</title>
<script src="playground-runtime.js"></script>
<style>
body { font-family: system-ui, sans-serif; max-width: 860px; margin: 2rem auto; padding: 0 1rem; color: #1a1a1a; }
h1 { font-size: 2rem; margin-bottom: .25rem; }
.subtitle { color: #555; margin-bottom: 2rem; }
section { margin-bottom: 2.5rem; }
h2 { font-size: 1.25rem; border-bottom: 2px solid #e0e0e0; padding-bottom: .35rem; margin-bottom: 1rem; }
pre { background: #f5f5f5; border-radius: 6px; padding: 1rem; overflow-x: auto; font-size: .875rem; }
code { font-family: "JetBrains Mono", "Fira Code", monospace; }
.output { background: #eaf7ea; border-left: 4px solid #4caf50; padding: .75rem 1rem; border-radius: 0 6px 6px 0; margin-top: .5rem; font-size: .875rem; white-space: pre; font-family: monospace; }
.note { background: #fff8e1; border-left: 4px solid #ffc107; padding: .6rem 1rem; border-radius: 0 6px 6px 0; font-size: .9rem; margin: .75rem 0; }
nav { margin-bottom: 1.5rem; font-size: .9rem; color: #555; }
nav a { color: #0366d6; text-decoration: none; }
nav a:hover { text-decoration: underline; }
:root {
--bg: #0d1117;
--surface: #161b22;
--border: #30363d;
--text: #e6edf3;
--accent: #58a6ff;
--green: #3fb950;
--orange: #d29922;
--red: #f85149;
--font-mono: "Cascadia Code", "Fira Code", "JetBrains Mono", monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--text);
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
padding: 2rem;
max-width: 900px;
margin: 0 auto;
}
a { color: var(--accent); }
h1 { color: var(--accent); margin-bottom: 0.5rem; }
h2 { margin-top: 0; margin-bottom: 0.5rem; font-size: 1.25rem; }
p { color: #8b949e; margin-bottom: 1rem; }
code {
font-family: var(--font-mono);
font-size: 0.875em;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 0.3rem;
padding: 0.1rem 0.4rem;
}
.back { margin-bottom: 2rem; display: inline-block; }
#playground-loading {
position: fixed;
inset: 0;
background: rgba(13, 17, 23, 0.92);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 1000;
gap: 1rem;
}
.spinner {
width: 40px; height: 40px;
border: 3px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
#playground-status { color: #8b949e; font-size: 0.95rem; }
.section {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 0.75rem;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.section p { margin-bottom: 0.75rem; }
.playground-block { margin-top: 0.75rem; }
.playground-header {
display: flex;
align-items: center;
justify-content: space-between;
background: #1c2128;
border: 1px solid var(--border);
border-bottom: none;
border-radius: 0.5rem 0.5rem 0 0;
padding: 0.4rem 0.75rem;
}
.playground-label {
font-size: 0.75rem;
color: #8b949e;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.playground-actions { display: flex; gap: 0.5rem; }
.playground-actions button {
background: transparent;
color: var(--accent);
border: 1px solid var(--border);
border-radius: 0.35rem;
padding: 0.25rem 0.7rem;
font-size: 0.8rem;
cursor: pointer;
font-family: system-ui, sans-serif;
transition: background 0.15s, border-color 0.15s;
}
.playground-actions button:hover:not(:disabled) {
background: rgba(88, 166, 255, 0.1);
border-color: var(--accent);
}
.playground-actions button:disabled { opacity: 0.4; cursor: not-allowed; }
.playground-run { font-weight: 600; }
.playground-editor {
display: block;
width: 100%;
min-height: 80px;
background: #0d1117;
color: var(--text);
border: 1px solid var(--border);
border-top: none;
border-bottom: none;
padding: 1rem;
font-family: var(--font-mono);
font-size: 0.875rem;
line-height: 1.55;
resize: vertical;
outline: none;
tab-size: 2;
white-space: pre;
overflow-x: auto;
}
.playground-editor:focus {
border-color: var(--accent);
box-shadow: inset 0 0 0 1px var(--accent);
}
.playground-output {
background: #1c2333;
border: 1px solid var(--border);
border-radius: 0 0 0.5rem 0.5rem;
padding: 0.75rem 1rem;
font-family: var(--font-mono);
font-size: 0.85rem;
color: #8b949e;
white-space: pre-wrap;
min-height: 2rem;
word-break: break-word;
}
.playground-output.active { color: var(--green); border-color: var(--green); }
.playground-output.error { color: var(--red); border-color: var(--red); }
.playground-hint {
font-size: 0.75rem;
color: #484f58;
margin-top: 0.35rem;
text-align: right;
}
.api-reference-code {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 0.5rem;
padding: 1rem;
font-family: var(--font-mono);
font-size: 0.85rem;
color: #8b949e;
overflow-x: auto;
margin-top: 0.5rem;
}
.api-reference-code code {
background: none;
border: none;
padding: 0;
}
footer {
text-align: center;
padding: 2rem 0;
color: #8b949e;
font-size: 0.85rem;
border-top: 1px solid var(--border);
margin-top: 2rem;
}
</style>
</head>
<body>
<nav><a href="index.html">← tsb playground</a></nav>
<h1>melt — Wide to Long</h1>
<p class="subtitle">Unpivot a DataFrame from wide format to long format — mirrors <code>pandas.melt()</code> / <code>DataFrame.melt()</code>.</p>
<div id="playground-loading">
<div class="spinner"></div>
<div id="playground-status">Initializing playground…</div>
</div>
<a class="back" href="index.html">← Back to roadmap</a>
<h1>🔄 melt — Interactive Playground</h1>
<p>Unpivot a DataFrame from wide format to long format — mirrors
<code>pandas.melt()</code> / <code>DataFrame.melt()</code>.<br>
<strong style="color: var(--text);">Edit any code block below and press ▶ Run
(or Ctrl+Enter) to execute it live in your browser.</strong>
</p>

<section>
<h2>1 — Basic melt</h2>
<p>Melt all value columns into a single <code>variable</code> / <code>value</code> pair.</p>
<pre><code id="ex1-code">import { DataFrame, melt } from "tsb";
<!-- 1 · Basic melt -->
<div class="section">
<h2>1 · Basic melt</h2>
<p>Melt all value columns into a single <code>variable</code> / <code>value</code>
pair.</p>
<div class="playground-block">
<div class="playground-header">
<span class="playground-label">TypeScript</span>
<div class="playground-actions">
<button class="playground-run" disabled>▶ Run</button>
<button class="playground-reset">↺ Reset</button>
</div>
</div>
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";

const df = DataFrame.fromColumns({
A: [1, 2, 3],
Expand All @@ -37,16 +206,26 @@ <h2>1 — Basic melt</h2>
});

const long = melt(df);
console.log(long.toRecords());
// [{ variable: "A", value: 1 }, { variable: "A", value: 2 }, ...]
</code></pre>
<div class="output" id="ex1-out">▶ run</div>
</section>
console.log(long.toRecords());</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<section>
<h2>2 — Preserve identifier columns</h2>
<p>Use <code>id_vars</code> to keep columns as identifiers that are repeated for each melted row.</p>
<pre><code id="ex2-code">import { DataFrame, melt } from "tsb";
<!-- 2 · Preserve identifier columns -->
<div class="section">
<h2>2 · Preserve identifier columns</h2>
<p>Use <code>id_vars</code> to keep columns as identifiers that are repeated for
each melted row.</p>
<div class="playground-block">
<div class="playground-header">
<span class="playground-label">TypeScript</span>
<div class="playground-actions">
<button class="playground-run" disabled>▶ Run</button>
<button class="playground-reset">↺ Reset</button>
</div>
</div>
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";

const df = DataFrame.fromColumns({
id: ["alice", "bob", "carol"],
Expand All @@ -55,16 +234,30 @@ <h2>2 — Preserve identifier columns</h2>
mar: [120, 210, 140],
});

const long = melt(df, { id_vars: "id", var_name: "month", value_name: "sales" });
console.log(long.toRecords());
</code></pre>
<div class="output" id="ex2-out">▶ run</div>
</section>
const long = melt(df, {
id_vars: "id",
var_name: "month",
value_name: "sales",
});
console.log(long.toRecords());</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<section>
<h2>3 — Selective value columns</h2>
<p>Use <code>value_vars</code> to specify which columns to unpivot.</p>
<pre><code id="ex3-code">import { DataFrame, melt } from "tsb";
<!-- 3 · Selective value columns -->
<div class="section">
<h2>3 · Selective value columns</h2>
<p>Use <code>value_vars</code> to specify which columns to unpivot.</p>
<div class="playground-block">
<div class="playground-header">
<span class="playground-label">TypeScript</span>
<div class="playground-actions">
<button class="playground-run" disabled>▶ Run</button>
<button class="playground-reset">↺ Reset</button>
</div>
</div>
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";

const df = DataFrame.fromColumns({
name: ["Alice", "Bob"],
Expand All @@ -73,22 +266,31 @@ <h2>3 — Selective value columns</h2>
grade: ["B", "A"],
});

// Only melt score columns, keep name
const long = melt(df, {
id_vars: "name",
value_vars: ["score1", "score2"],
var_name: "test",
value_name: "score",
});
console.log(long.toRecords());
</code></pre>
<div class="output" id="ex3-out">▶ run</div>
</section>
console.log(long.toRecords());</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<section>
<h2>4 — Multiple id columns</h2>
<p>Pass an array to <code>id_vars</code> to use multiple identifier columns.</p>
<pre><code id="ex4-code">import { DataFrame, melt } from "tsb";
<!-- 4 · Multiple id columns -->
<div class="section">
<h2>4 · Multiple id columns</h2>
<p>Pass an array to <code>id_vars</code> to use multiple identifier columns.</p>
<div class="playground-block">
<div class="playground-header">
<span class="playground-label">TypeScript</span>
<div class="playground-actions">
<button class="playground-run" disabled>▶ Run</button>
<button class="playground-reset">↺ Reset</button>
</div>
</div>
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";

const df = DataFrame.fromColumns({
year: [2022, 2023],
Expand All @@ -102,28 +304,32 @@ <h2>4 — Multiple id columns</h2>
var_name: "quarter",
value_name: "revenue",
});
console.log(long.toRecords());
</code></pre>
<div class="output" id="ex4-out">▶ run</div>
</section>
console.log(long.toRecords());</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<script>
window.addEventListener("load", () => {
document.querySelectorAll(".output").forEach((el) => {
const id = el.id.replace("-out", "-code");
const code = document.getElementById(id)?.textContent ?? "";
el.textContent = "▶ click to run";
el.style.cursor = "pointer";
el.addEventListener("click", () => {
el.textContent = "Running…";
try {
window.runTsb?.(code, (result) => { el.textContent = result; });
} catch (e) {
el.textContent = String(e);
}
});
});
});
</script>
<!-- API Reference -->
<div class="section">
<h2>API Reference</h2>
<p>Unpivot a DataFrame from wide to long format. Columns not specified as
<code>id_vars</code> or <code>value_vars</code> are melted into
<code>variable</code> / <code>value</code> pairs.</p>
<pre class="api-reference-code"><code>melt(df: DataFrame, options?: {
id_vars?: string | string[], // columns to keep as identifiers
value_vars?: string | string[], // columns to unpivot (default: all non-id)
var_name?: string, // name for the variable column (default: "variable")
value_name?: string, // name for the value column (default: "value")
}): DataFrame</code></pre>
</div>

<footer>
<p>
<a href="index.html">tsb playground</a> ·
Built by <a href="https://github.com/githubnext/autoloop">Autoloop</a>
</p>
</footer>
<script type="module" src="playground-runtime.js"></script>
</body>
</html>
Loading
Loading