Requires statsmodels, NumPy, and SciPy.
from statsmodels.stats.power import FTestAnovaPower
import numpy as np
# Parameters
k = 3 # Number of groups
f = 0.25 # Cohen's f (medium effect size)
alpha = 0.05 # Significance level
power = 0.8 # Desired power
# Create power analysis object
analysis = FTestAnovaPower()
# Calculate TOTAL sample size first (statsmodels returns total, not per-group)
total_sample_size = analysis.solve_power(
effect_size=f,
nobs=None,
alpha=alpha,
power=power,
k_groups=k
)
# Handle array conversion (statsmodels may return array)
if isinstance(total_sample_size, np.ndarray):
total_sample_size = float(total_sample_size.item())
else:
total_sample_size = float(total_sample_size)
# Divide by k to get per-group size
per_group = total_sample_size / k
n_per_group = int(np.ceil(per_group))
balanced_total = n_per_group * k
print(f"Sample size per group: {n_per_group}")
print(f"Total sample size: {balanced_total}")
# Also calculate what power we'd have with different sample sizes
for n_per_group in [30, 50, 70, 100]:
# Note: nobs must be TOTAL sample size (per-group × k)
pwr = analysis.power(
effect_size=f,
nobs=n_per_group * k,
alpha=alpha,
k_groups=k
)
print(f"Power with n={n_per_group} per group: {pwr:.3f} ({pwr*100:.1f}%)")
Output
Sample size per group: 53
Total sample size: 159
Power with n=30 per group: 0.540 (54.0%)
Power with n=50 per group: 0.780 (78.0%)
Power with n=70 per group: 0.907 (90.7%)
Power with n=100 per group: 0.978 (97.8%)