Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
702935b
[Autoloop: perf-comparison] Iteration 392: gaussianKDE benchmark pair
github-actions[bot] Jul 10, 2026
9184f78
ci: trigger checks
github-actions[bot] Jul 10, 2026
4d9c9c8
[Autoloop: perf-comparison] Iteration 393: hypothesis_tests benchmark
github-actions[bot] Jul 11, 2026
dee50e0
ci: trigger checks
github-actions[bot] Jul 11, 2026
00591a9
[Autoloop: perf-comparison] Iteration 394: entropy/klDivergence bench…
github-actions[bot] Jul 11, 2026
208bf94
ci: trigger checks
github-actions[bot] Jul 11, 2026
1931df8
[Autoloop: perf-comparison] Iteration 395: mutualInformation/normaliz…
github-actions[bot] Jul 12, 2026
5a75569
ci: trigger checks
github-actions[bot] Jul 12, 2026
53d0b77
[Autoloop: perf-comparison] Iteration 396: lreshape + linregress/poly…
github-actions[bot] Jul 12, 2026
5222e78
ci: trigger checks
github-actions[bot] Jul 12, 2026
c460e76
[Autoloop: perf-comparison] Iteration 397: contingency benchmark
github-actions[bot] Jul 13, 2026
5d1b2ca
ci: trigger checks
github-actions[bot] Jul 13, 2026
fb08d7a
[Autoloop: perf-comparison] Iteration 398: multivariate benchmark (ma…
github-actions[bot] Jul 13, 2026
b768b7d
ci: trigger checks
github-actions[bot] Jul 13, 2026
1dce402
[Autoloop: perf-comparison] Iteration 399: IntegerArray/FloatingArray…
github-actions[bot] Jul 14, 2026
a4e6690
ci: trigger checks
github-actions[bot] Jul 14, 2026
22ac492
[Autoloop: perf-comparison] Iteration 400: FloatingArray benchmark
github-actions[bot] Jul 14, 2026
12f45c0
ci: trigger checks
github-actions[bot] Jul 14, 2026
da47672
[Autoloop: perf-comparison] Iteration 401: add pipe_apply benchmark pair
github-actions[bot] Jul 15, 2026
03cbe04
ci: trigger checks
github-actions[bot] Jul 15, 2026
0429685
[Autoloop: perf-comparison] Iteration 402: readXml/toXml benchmark
github-actions[bot] Jul 15, 2026
7d13f40
ci: trigger checks
github-actions[bot] Jul 15, 2026
7bc9b56
[Autoloop: perf-comparison] Iteration 403: flags+options benchmark
github-actions[bot] Jul 16, 2026
ed8617f
ci: trigger checks
github-actions[bot] Jul 16, 2026
5a00c76
[Autoloop: perf-comparison] Iteration 404: case_when benchmark (N=100…
github-actions[bot] Jul 16, 2026
296e294
ci: trigger checks
github-actions[bot] Jul 16, 2026
2865f3b
[Autoloop: perf-comparison] Iteration 405: readSqlQuery/toSql benchma…
github-actions[bot] Jul 17, 2026
cada908
ci: trigger checks
github-actions[bot] Jul 17, 2026
e286683
[Autoloop: perf-comparison] Iteration 406: readSas benchmark (1k rows…
github-actions[bot] Jul 17, 2026
36f244d
ci: trigger checks
github-actions[bot] Jul 17, 2026
d95bec2
[Autoloop: perf-comparison] Iteration 407: add toExcel benchmark pair
github-actions[bot] Jul 18, 2026
185e250
ci: trigger checks
github-actions[bot] Jul 18, 2026
7505d03
[Autoloop: perf-comparison] Iteration 408: add readFwf benchmark pair
github-actions[bot] Jul 18, 2026
4544000
ci: trigger checks
github-actions[bot] Jul 18, 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
35 changes: 35 additions & 0 deletions benchmarks/pandas/bench_case_when.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Benchmark: case_when — conditional value selection on 100k-element Series (pandas 2.2+)"""
import json, time
import numpy as np
import pandas as pd

ROWS = 100_000
WARMUP = 5
ITERATIONS = 20

data = np.arange(ROWS, dtype=float) % 100
s = pd.Series(data)
cond1 = s < 25
cond2 = s < 50
cond3 = s < 75

caselist = [
(cond1, "low"),
(cond2, "medium-low"),
(cond3, "medium-high"),
]

for _ in range(WARMUP):
s.case_when(caselist)

start = time.perf_counter()
for _ in range(ITERATIONS):
s.case_when(caselist)
total = (time.perf_counter() - start) * 1000

print(json.dumps({
"function": "case_when",
"mean_ms": total / ITERATIONS,
"iterations": ITERATIONS,
"total_ms": total,
}))
78 changes: 78 additions & 0 deletions benchmarks/pandas/bench_contingency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
Benchmark: contingency — expected_freq, relative_risk, odds_ratio, association
Pure-numpy equivalents (no scipy) matching the TypeScript benchmark.
Dataset: same 4x4 table as the TypeScript benchmark.
"""
import json
import time
import numpy as np

WARMUP = 10
ITERS = 50

observed = np.array([
[120, 80, 40, 60],
[90, 110, 70, 30],
[50, 60, 100, 90],
[40, 50, 90, 120],
], dtype=float)

two_by_two = np.array([
[60.0, 40.0],
[30.0, 70.0],
])


def expected_freq(obs):
row_sums = obs.sum(axis=1, keepdims=True)
col_sums = obs.sum(axis=0, keepdims=True)
total = obs.sum()
return row_sums * col_sums / total


def relative_risk(obs):
a, b = obs[0, 0], obs[0, 1]
c, d = obs[1, 0], obs[1, 1]
risk0 = a / (a + b)
risk1 = c / (c + d)
return risk0 / risk1


def odds_ratio(obs):
a, b = obs[0, 0], obs[0, 1]
c, d = obs[1, 0], obs[1, 1]
return (a * d) / (b * c)


def association_cramer(obs):
exp = expected_freq(obs)
chi2 = np.sum((obs - exp) ** 2 / exp)
n = obs.sum()
r, c = obs.shape
return np.sqrt(chi2 / n / min(r - 1, c - 1))


# Warm up
for _ in range(WARMUP):
expected_freq(observed)
relative_risk(two_by_two)
odds_ratio(two_by_two)
association_cramer(observed)

# Measure
start = time.perf_counter()
for _ in range(ITERS):
expected_freq(observed)
relative_risk(two_by_two)
odds_ratio(two_by_two)
association_cramer(observed)
total_s = time.perf_counter() - start
total_ms = total_s * 1000
mean_ms = total_ms / ITERS

print(json.dumps({
"function": "contingency",
"mean_ms": round(mean_ms, 4),
"iterations": ITERS,
"total_ms": round(total_ms, 4),
}))
44 changes: 44 additions & 0 deletions benchmarks/pandas/bench_entropy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import numpy as np
import json
import time

N = 100
WARMUP = 5
ITERS = 50

p = np.arange(1, N + 1, dtype=float)
q = np.arange(N, 0, -1, dtype=float)

# Normalise
p_norm = p / p.sum()
q_norm = q / q.sum()


def entropy_fn(pk):
pk = pk / pk.sum()
return -np.sum(pk * np.log(pk + 1e-300))


def kl_divergence(pk, qk):
pk = pk / pk.sum()
qk = qk / qk.sum()
mask = pk > 0
return np.sum(pk[mask] * np.log(pk[mask] / (qk[mask] + 1e-300)))


for _ in range(WARMUP):
entropy_fn(p)
kl_divergence(p, q)

t0 = time.perf_counter()
for _ in range(ITERS):
entropy_fn(p)
kl_divergence(p, q)
total_ms = (time.perf_counter() - t0) * 1000

print(json.dumps({
"function": "entropy_klDivergence",
"mean_ms": total_ms / ITERS,
"iterations": ITERS,
"total_ms": total_ms,
}))
73 changes: 73 additions & 0 deletions benchmarks/pandas/bench_flags_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
Benchmark: flags and options (pandas equivalent)

Measures:
- DataFrame.flags.allows_duplicate_labels get+set
- pd.get_option / pd.set_option / pd.reset_option for multiple keys
- pd.options proxy read

Dataset: 10,000-row Series and DataFrame; 20 measured iterations.
"""

import json
import time

import numpy as np
import pandas as pd

N = 10_000
WARMUP = 5
ITERS = 20

data = np.arange(N, dtype=np.float64)
s = pd.Series(data)
df = pd.DataFrame({"a": data, "b": data})


def bench_flags_options():
sink = 0
for _ in range(ITERS + WARMUP):
# flags on Series
prev = s.flags.allows_duplicate_labels
s.flags.allows_duplicate_labels = not prev
s.flags.allows_duplicate_labels = prev
sink ^= int(s.flags.allows_duplicate_labels)

# flags on DataFrame
prev_df = df.flags.allows_duplicate_labels
df.flags.allows_duplicate_labels = not prev_df
df.flags.allows_duplicate_labels = prev_df
sink ^= int(df.flags.allows_duplicate_labels)

# options get/set/reset
v = pd.get_option("display.max_rows")
pd.set_option("display.max_rows", v + 1)
pd.reset_option("display.max_rows")
sink ^= int(pd.options.display.max_rows > 0)

pd.set_option("display.max_columns", 20)
pd.reset_option("display.max_columns")
sink ^= int(pd.options.display.max_columns > 0)

return sink


# Warm-up
bench_flags_options()

# Measure
t0 = time.perf_counter()
for _ in range(ITERS):
bench_flags_options()
total = (time.perf_counter() - t0) * 1000 # ms

print(
json.dumps(
{
"function": "flags_options",
"mean_ms": total / ITERS,
"iterations": ITERS,
"total_ms": total,
}
)
)
42 changes: 42 additions & 0 deletions benchmarks/pandas/bench_floating_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
Benchmark: FloatingArray (pandas Float64 nullable float array).
N=100_000 elements with ~10% nulls. Tests from/sum/mean/min/max/add/fillna.
"""
import json
import time

import pandas as pd
import numpy as np

N = 100_000
WARMUP = 3
ITERATIONS = 20

raw = [None if i % 10 == 0 else (i % 1000) * 0.001 - 0.5 for i in range(N)]

for _ in range(WARMUP):
a = pd.array(raw, dtype="Float64")
float(a.sum())
float(a.mean())
float(a.min())
float(a.max())
a + 1.0
a.fillna(0.0)

start = time.perf_counter()
for _ in range(ITERATIONS):
a = pd.array(raw, dtype="Float64")
float(a.sum())
float(a.mean())
float(a.min())
float(a.max())
a + 1.0
a.fillna(0.0)
total = (time.perf_counter() - start) * 1000

print(json.dumps({
"function": "floating_array",
"mean_ms": total / ITERATIONS,
"iterations": ITERATIONS,
"total_ms": total,
}))
45 changes: 45 additions & 0 deletions benchmarks/pandas/bench_gaussianKDE.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Benchmark: Gaussian KDE evaluate on 1000-point dataset at 200 grid points.
Uses Scott bandwidth (numpy equivalent of Silverman for univariate data).
Pure numpy implementation to match pages workflow constraints.
"""
import json
import time
import numpy as np

N = 1_000
GRID = 200
WARMUP = 3
ITERATIONS = 20

# Create dataset: mix of two gaussians (same as TS benchmark)
i_vals = np.arange(N)
data = np.sin(i_vals * 0.01) * 2 + np.where(i_vals % 2 == 0, 0.0, 5.0)

xmin, xmax = -5.0, 10.0
grid = np.linspace(xmin, xmax, GRID)


def gaussian_kde_evaluate(data: np.ndarray, points: np.ndarray) -> np.ndarray:
"""Gaussian KDE with Silverman bandwidth, pure numpy."""
n = len(data)
std = np.std(data, ddof=1)
bw = (4.0 / (3.0 * n)) ** 0.2 * std # Silverman rule
diff = points[:, np.newaxis] - data[np.newaxis, :] # (GRID, N)
kernels = np.exp(-0.5 * (diff / bw) ** 2) / (bw * np.sqrt(2 * np.pi))
return kernels.mean(axis=1)


for _ in range(WARMUP):
gaussian_kde_evaluate(data, grid)

start = time.perf_counter()
for _ in range(ITERATIONS):
gaussian_kde_evaluate(data, grid)
total = (time.perf_counter() - start) * 1000

print(json.dumps({
"function": "gaussianKDE",
"mean_ms": total / ITERATIONS,
"iterations": ITERATIONS,
"total_ms": total,
}))
Loading
Loading