Skip to content

Commit f700047

Browse files
Iteration 169: Add 10 benchmark pairs (549 total, +5 vs best 544)
Added 10 new benchmark pairs covering specific options/variants: - read_json_all_orients: readJson with records/split/columns/values/index orients - pivot_table_fill_value: pivotTable with fill_value=0 option - dataframe_cov_options: dataFrameCov/dataFrameCorr with ddof and minPeriods - dataframe_rolling_apply_fn: standalone dataFrameRollingApply function - pct_change_fill_method: pctChangeSeries/pctChangeDataFrame with fillMethod options - reindex_fill_methods: reindexSeries/reindexDataFrame with ffill/bfill/nearest - json_normalize_meta: jsonNormalize with recordPath, meta fields, metaPrefix - interpolate_zero_nearest: interpolateSeries with zero/nearest/linear with limit - dropna_thresh_subset: dropnaDataFrame with thresh and subset options - wide_to_long_sep_suffix: wideToLong with sep and suffix regex options Run: https://github.com/githubnext/tsessebe/actions/runs/24590758458 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6609544 commit f700047

20 files changed

Lines changed: 802 additions & 0 deletions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Benchmark: DataFrame.cov / DataFrame.corr with options (ddof, min_periods)."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
SIZE = 20_000
7+
WARMUP = 3
8+
ITERATIONS = 20
9+
10+
rng = np.random.default_rng(42)
11+
a = np.arange(SIZE) * 0.5 + np.sin(np.arange(SIZE) * 0.01)
12+
b = np.arange(SIZE) * 0.3 - np.cos(np.arange(SIZE) * 0.02)
13+
c = (np.arange(SIZE) % 100) * 1.5
14+
df = pd.DataFrame({"a": a, "b": b, "c": c})
15+
16+
for _ in range(WARMUP):
17+
df.cov(ddof=0)
18+
df.cov(ddof=1, min_periods=100)
19+
df.corr(min_periods=50)
20+
21+
start = time.perf_counter()
22+
for _ in range(ITERATIONS):
23+
df.cov(ddof=0)
24+
df.cov(ddof=1, min_periods=100)
25+
df.corr(min_periods=50)
26+
total = (time.perf_counter() - start) * 1000
27+
28+
print(json.dumps({
29+
"function": "dataframe_cov_options",
30+
"mean_ms": total / ITERATIONS,
31+
"iterations": ITERATIONS,
32+
"total_ms": total,
33+
}))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: DataFrame rolling apply with a custom range function per column."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
ROWS = 5_000
7+
WINDOW = 10
8+
WARMUP = 3
9+
ITERATIONS = 10
10+
11+
a = np.sin(np.arange(ROWS) * 0.01)
12+
b = np.cos(np.arange(ROWS) * 0.02)
13+
c = (np.arange(ROWS) % 100) * 0.5
14+
df = pd.DataFrame({"a": a, "b": b, "c": c})
15+
16+
range_fn = lambda w: np.max(w) - np.min(w)
17+
18+
for _ in range(WARMUP):
19+
df.rolling(WINDOW).apply(range_fn, raw=True)
20+
21+
start = time.perf_counter()
22+
for _ in range(ITERATIONS):
23+
df.rolling(WINDOW).apply(range_fn, raw=True)
24+
total = (time.perf_counter() - start) * 1000
25+
26+
print(json.dumps({
27+
"function": "dataframe_rolling_apply_fn",
28+
"mean_ms": total / ITERATIONS,
29+
"iterations": ITERATIONS,
30+
"total_ms": total,
31+
}))
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Benchmark: DataFrame.dropna with thresh and subset options."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
SIZE = 100_000
7+
WARMUP = 5
8+
ITERATIONS = 30
9+
10+
a = [None if i % 5 == 0 else float(i) for i in range(SIZE)]
11+
b = [None if i % 7 == 0 else float(i * 2) for i in range(SIZE)]
12+
c = [None if i % 11 == 0 else float(i * 3) for i in range(SIZE)]
13+
d = [None if i % 3 == 0 else f"label_{i % 20}" for i in range(SIZE)]
14+
df = pd.DataFrame({"a": a, "b": b, "c": c, "d": d})
15+
16+
for _ in range(WARMUP):
17+
df.dropna(how="any")
18+
df.dropna(how="all")
19+
df.dropna(thresh=3)
20+
df.dropna(subset=["a", "b"])
21+
22+
start = time.perf_counter()
23+
for _ in range(ITERATIONS):
24+
df.dropna(how="any")
25+
df.dropna(how="all")
26+
df.dropna(thresh=3)
27+
df.dropna(subset=["a", "b"])
28+
total = (time.perf_counter() - start) * 1000
29+
30+
print(json.dumps({
31+
"function": "dropna_thresh_subset",
32+
"mean_ms": total / ITERATIONS,
33+
"iterations": ITERATIONS,
34+
"total_ms": total,
35+
}))
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Benchmark: Series.interpolate with zero and nearest methods."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
SIZE = 50_000
7+
WARMUP = 5
8+
ITERATIONS = 30
9+
10+
data = [None if i % 7 in (0, 1, 2) else np.sin(i * 0.01) * 100 for i in range(SIZE)]
11+
s = pd.Series(data, dtype="float64")
12+
13+
for _ in range(WARMUP):
14+
s.interpolate(method="zero")
15+
s.interpolate(method="nearest")
16+
s.interpolate(method="linear", limit=2)
17+
s.interpolate(method="pad", limit=5)
18+
19+
start = time.perf_counter()
20+
for _ in range(ITERATIONS):
21+
s.interpolate(method="zero")
22+
s.interpolate(method="nearest")
23+
s.interpolate(method="linear", limit=2)
24+
s.interpolate(method="pad", limit=5)
25+
total = (time.perf_counter() - start) * 1000
26+
27+
print(json.dumps({
28+
"function": "interpolate_zero_nearest",
29+
"mean_ms": total / ITERATIONS,
30+
"iterations": ITERATIONS,
31+
"total_ms": total,
32+
}))
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Benchmark: pd.json_normalize with record_path, meta fields, and nested data."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 2_000
6+
WARMUP = 3
7+
ITERATIONS = 20
8+
9+
records = [
10+
{
11+
"id": i,
12+
"dept": f"dept_{i % 10}",
13+
"location": {"city": f"city_{i % 20}", "country": "US"},
14+
"employees": [
15+
{"name": f"emp_{i}_{j}", "salary": (i * 3 + j) * 1000, "active": j % 2 == 0}
16+
for j in range(3)
17+
],
18+
}
19+
for i in range(SIZE)
20+
]
21+
22+
for _ in range(WARMUP):
23+
pd.json_normalize(
24+
records,
25+
record_path="employees",
26+
meta=["id", "dept"],
27+
meta_prefix="company_",
28+
)
29+
30+
start = time.perf_counter()
31+
for _ in range(ITERATIONS):
32+
pd.json_normalize(
33+
records,
34+
record_path="employees",
35+
meta=["id", "dept"],
36+
meta_prefix="company_",
37+
)
38+
total = (time.perf_counter() - start) * 1000
39+
40+
print(json.dumps({
41+
"function": "json_normalize_meta",
42+
"mean_ms": total / ITERATIONS,
43+
"iterations": ITERATIONS,
44+
"total_ms": total,
45+
}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Benchmark: Series.pct_change / DataFrame.pct_change with fill_method options."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
SIZE = 50_000
7+
WARMUP = 5
8+
ITERATIONS = 30
9+
10+
data = [None if i % 20 == 0 else np.sin(i * 0.01) * 100 + 100 for i in range(SIZE)]
11+
s = pd.Series(data, dtype="float64")
12+
13+
df = pd.DataFrame({
14+
"a": data,
15+
"b": [None if i % 15 == 0 else np.cos(i * 0.02) * 50 + 50 for i in range(SIZE)],
16+
})
17+
18+
for _ in range(WARMUP):
19+
s.pct_change(fill_method="pad")
20+
s.pct_change(fill_method="bfill")
21+
s.pct_change(fill_method=None)
22+
df.pct_change(fill_method="pad", periods=2)
23+
24+
start = time.perf_counter()
25+
for _ in range(ITERATIONS):
26+
s.pct_change(fill_method="pad")
27+
s.pct_change(fill_method="bfill")
28+
s.pct_change(fill_method=None)
29+
df.pct_change(fill_method="pad", periods=2)
30+
total = (time.perf_counter() - start) * 1000
31+
32+
print(json.dumps({
33+
"function": "pct_change_fill_method",
34+
"mean_ms": total / ITERATIONS,
35+
"iterations": ITERATIONS,
36+
"total_ms": total,
37+
}))
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Benchmark: pivot_table with fill_value=0 — fills missing cells with 0."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
ROWS = 50_000
7+
WARMUP = 3
8+
ITERATIONS = 10
9+
10+
rows = [f"row_{i % 50}" for i in range(ROWS)]
11+
cols = [f"col_{i % 30}" for i in range(ROWS)]
12+
vals = np.arange(ROWS, dtype=np.float64) * 0.1
13+
df = pd.DataFrame({"row": rows, "col": cols, "value": vals})
14+
15+
for _ in range(WARMUP):
16+
df.pivot_table(values="value", index="row", columns="col", aggfunc="sum", fill_value=0)
17+
18+
start = time.perf_counter()
19+
for _ in range(ITERATIONS):
20+
df.pivot_table(values="value", index="row", columns="col", aggfunc="sum", fill_value=0)
21+
total = (time.perf_counter() - start) * 1000
22+
23+
print(json.dumps({
24+
"function": "pivot_table_fill_value",
25+
"mean_ms": total / ITERATIONS,
26+
"iterations": ITERATIONS,
27+
"total_ms": total,
28+
}))
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""Benchmark: pd.read_json with all orient options (records, split, columns, index, values)."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
SIZE = 5_000
7+
WARMUP = 3
8+
ITERATIONS = 20
9+
10+
ids = list(range(SIZE))
11+
values = [i * 1.1 for i in range(SIZE)]
12+
labels = [f"cat_{i % 10}" for i in range(SIZE)]
13+
df = pd.DataFrame({"id": ids, "value": values, "label": labels})
14+
15+
records_json = df.to_json(orient="records")
16+
split_json = df.to_json(orient="split")
17+
columns_json = df.to_json(orient="columns")
18+
values_json = df.to_json(orient="values")
19+
index_json = df.to_json(orient="index")
20+
21+
for _ in range(WARMUP):
22+
pd.read_json(records_json, orient="records")
23+
pd.read_json(split_json, orient="split")
24+
pd.read_json(columns_json, orient="columns")
25+
pd.read_json(values_json, orient="values")
26+
pd.read_json(index_json, orient="index")
27+
28+
start = time.perf_counter()
29+
for _ in range(ITERATIONS):
30+
pd.read_json(records_json, orient="records")
31+
pd.read_json(split_json, orient="split")
32+
pd.read_json(columns_json, orient="columns")
33+
pd.read_json(values_json, orient="values")
34+
pd.read_json(index_json, orient="index")
35+
total = (time.perf_counter() - start) * 1000
36+
37+
print(json.dumps({
38+
"function": "read_json_all_orients",
39+
"mean_ms": total / ITERATIONS,
40+
"iterations": ITERATIONS,
41+
"total_ms": total,
42+
}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Benchmark: Series.reindex / DataFrame.reindex with fill methods (ffill, bfill, nearest)."""
2+
import json, time
3+
import numpy as np
4+
import pandas as pd
5+
6+
SIZE = 20_000
7+
WARMUP = 3
8+
ITERATIONS = 20
9+
10+
orig_labels = list(range(0, SIZE * 2, 2)) # even numbers
11+
data = [i * 1.5 for i in range(SIZE)]
12+
s = pd.Series(data, index=orig_labels)
13+
14+
new_index = list(range(SIZE * 2)) # all numbers 0..SIZE*2-1
15+
16+
df = pd.DataFrame({"a": data, "b": [v * 2 for v in data]}, index=orig_labels)
17+
18+
for _ in range(WARMUP):
19+
s.reindex(new_index, method="ffill")
20+
s.reindex(new_index, method="bfill")
21+
s.reindex(new_index, method="nearest")
22+
df.reindex(new_index, method="ffill")
23+
24+
start = time.perf_counter()
25+
for _ in range(ITERATIONS):
26+
s.reindex(new_index, method="ffill")
27+
s.reindex(new_index, method="bfill")
28+
s.reindex(new_index, method="nearest")
29+
df.reindex(new_index, method="ffill")
30+
total = (time.perf_counter() - start) * 1000
31+
32+
print(json.dumps({
33+
"function": "reindex_fill_methods",
34+
"mean_ms": total / ITERATIONS,
35+
"iterations": ITERATIONS,
36+
"total_ms": total,
37+
}))
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Benchmark: pd.wide_to_long with sep and suffix options."""
2+
import json, time
3+
import pandas as pd
4+
5+
ROWS = 5_000
6+
WARMUP = 3
7+
ITERATIONS = 20
8+
9+
ids = list(range(ROWS))
10+
df1 = pd.DataFrame({
11+
"id": ids,
12+
"A_1": [i * 1.0 for i in ids],
13+
"A_2": [i * 1.1 for i in ids],
14+
"A_3": [i * 1.2 for i in ids],
15+
"B_1": [i * 2.0 for i in ids],
16+
"B_2": [i * 2.1 for i in ids],
17+
"B_3": [i * 2.2 for i in ids],
18+
})
19+
20+
students = [f"s{i}" for i in ids]
21+
df2 = pd.DataFrame({
22+
"student": students,
23+
"score_Q1": [i + 10 for i in ids],
24+
"score_Q2": [i + 20 for i in ids],
25+
"score_Q3": [i + 30 for i in ids],
26+
})
27+
28+
for _ in range(WARMUP):
29+
pd.wide_to_long(df1, stubnames=["A", "B"], i="id", j="period", sep="_")
30+
pd.wide_to_long(df2, stubnames="score", i="student", j="quarter", sep="_", suffix=r"Q\d+")
31+
32+
start = time.perf_counter()
33+
for _ in range(ITERATIONS):
34+
pd.wide_to_long(df1, stubnames=["A", "B"], i="id", j="period", sep="_")
35+
pd.wide_to_long(df2, stubnames="score", i="student", j="quarter", sep="_", suffix=r"Q\d+")
36+
total = (time.perf_counter() - start) * 1000
37+
38+
print(json.dumps({
39+
"function": "wide_to_long_sep_suffix",
40+
"mean_ms": total / ITERATIONS,
41+
"iterations": ITERATIONS,
42+
"total_ms": total,
43+
}))

0 commit comments

Comments
 (0)