Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
355 changes: 355 additions & 0 deletions playground/asfreq.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>tsb — asfreq — tsb playground</title>
<style>
: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; }
.subtitle { margin-bottom: 1.5rem; }

#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;
}

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>


<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>asfreq — tsb playground</h1>
<p class="subtitle">Convert a datetime-indexed Series or DataFrame to a specified
frequency. Mirrors <code>pandas.Series.asfreq</code> and
<code>pandas.DataFrame.asfreq</code>. Unlike <code>resample</code> (which groups
and aggregates), <code>asfreq</code> simply reindexes onto a regular grid at the
new frequency &mdash; upsampled gaps are <code>null</code> unless <code>method</code>
or <code>fillValue</code> is given, and downsampled rows not on the new grid are
dropped.</p>

<div class="section">
<h2>asfreqSeries — upsampling introduces null gaps</h2>
<p>Python pandas equivalent:</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 pandas as pd

idx = pd.date_range("2024-01-01", periods=3, freq="D")
s = pd.Series([1, 2, 3], index=idx, name="vals")

print(s.asfreq("12h").values)
# [1.0, nan, 2.0, nan, 3.0]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqSeries — upsampling introduces null gaps</h2>
<p>Python pandas equivalent:</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 { Hour, Series, asfreqSeries, date_range } from "tsb";

const idx = date_range({ start: "2024-01-01", periods: 3, freq: "D" }).toArray();
const s = new Series({ data: [1, 2, 3], index: idx, name: "vals" });

console.log(asfreqSeries(s, new Hour(12)).values); // [1, null, 2, null, 3]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqSeries — method / fillValue fill gaps introduced by upsampling</h2>
<p>Python pandas equivalent:</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 pandas as pd

idx = pd.date_range("2024-01-01", periods=3, freq="D")
s = pd.Series([1, 2, 3], index=idx)

print(s.asfreq("12h", method="ffill").values)
# [1, 1, 2, 2, 3]

print(s.asfreq("12h", fill_value=-1).values)
# [1, -1, 2, -1, 3]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqSeries — method / fillValue fill gaps introduced by upsampling</h2>
<p>Python pandas equivalent:</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 { Hour, Series, asfreqSeries, date_range } from "tsb";

const idx = date_range({ start: "2024-01-01", periods: 3, freq: "D" }).toArray();
const s = new Series({ data: [1, 2, 3], index: idx });

console.log(asfreqSeries(s, new Hour(12), { method: "ffill" }).values); // [1, 1, 2, 2, 3]
console.log(asfreqSeries(s, new Hour(12), { fillValue: -1 }).values); // [1, -1, 2, -1, 3]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqSeries — downsampling drops rows not on the new grid</h2>
<p>Python pandas equivalent:</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 pandas as pd

idx = pd.date_range("2024-01-01", periods=6, freq="D")
s = pd.Series(range(6), index=idx)

print(s.asfreq("2D").values)
# [0, 2, 4]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqSeries — downsampling drops rows not on the new grid</h2>
<p>Python pandas equivalent:</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 { Day, Series, asfreqSeries, date_range } from "tsb";

const idx = date_range({ start: "2024-01-01", periods: 6, freq: "D" }).toArray();
const s = new Series({ data: [0, 1, 2, 3, 4, 5], index: idx });

console.log(asfreqSeries(s, new Day(2)).values); // [0, 2, 4]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqDataFrame — applies to every column</h2>
<p>Python pandas equivalent:</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 pandas as pd

idx = pd.date_range("2024-01-01", periods=3, freq="D")
df = pd.DataFrame({"a": [1, 2, 3], "b": [10, 20, 30]}, index=idx)

print(df.asfreq("12h", method="ffill").to_dict("list"))
# {'a': [1, 1, 2, 2, 3], 'b': [10, 10, 20, 20, 30]}</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</div>

<div class="section">
<h2>asfreqDataFrame — applies to every column</h2>
<p>Python pandas equivalent:</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, Hour, asfreqDataFrame, date_range } from "tsb";

const idx = date_range({ start: "2024-01-01", periods: 3, freq: "D" }).toArray();
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [10, 20, 30] }, { index: idx });

const r = asfreqDataFrame(df, new Hour(12), { method: "ffill" });
console.log(r.col("a").values); // [1, 1, 2, 2, 3]
console.log(r.col("b").values); // [10, 10, 20, 20, 30]</textarea>
<div class="playground-output">Click ▶ Run to execute</div>
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
</div>
</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