
Statistical Analysis
- 49 installs
- 4 repo stars
- Updated January 5, 2026
- pluginagentmarketplace/custom-plugin-ai-data-scientist
statistical-analysis is a Claude Code skill for ai & agent building.
About
statistical-analysis is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- statistical-analysis
- AI & Agent Building
- AI-coding skill
Statistical Analysis by the numbers
- 49 all-time installs (skills.sh)
- Ranked #7,329 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-ai-data-scientist --skill statistical-analysisAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 49 |
|---|---|
| repo stars | ★ 4 |
| Last updated | January 5, 2026 |
| Repository | pluginagentmarketplace/custom-plugin-ai-data-scientist ↗ |
How do I helps with ai & agent building tasks.?
Helps with ai & agent building tasks.
Who is it for?
Best when you're working on ai & agent building and need structured help with statistical analysis.
Skip if: Teams with no ai & agent building needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to helps with ai & agent building tasks., or when statistical-analysis is a claude code skill for ai & agent building.
What you get
Structured output aligned to statistical-analysis: statistical-analysis, AI & Agent Building.
Files
Statistical Analysis
Apply statistical methods to understand data and validate findings.
Quick Start
from scipy import stats
import numpy as np
# Descriptive statistics
data = np.array([1, 2, 3, 4, 5])
print(f"Mean: {np.mean(data)}")
print(f"Std: {np.std(data)}")
# Hypothesis testing
group1 = [23, 25, 27, 29, 31]
group2 = [20, 22, 24, 26, 28]
t_stat, p_value = stats.ttest_ind(group1, group2)
print(f"P-value: {p_value}")Core Tests
T-Test (Compare Means)
# One-sample: Compare to population mean
stats.ttest_1samp(data, 100)
# Two-sample: Compare two groups
stats.ttest_ind(group1, group2)
# Paired: Before/after comparison
stats.ttest_rel(before, after)Chi-Square (Categorical Data)
from scipy.stats import chi2_contingency
observed = np.array([[10, 20], [15, 25]])
chi2, p_value, dof, expected = chi2_contingency(observed)ANOVA (Multiple Groups)
f_stat, p_value = stats.f_oneway(group1, group2, group3)Confidence Intervals
from scipy import stats
confidence_level = 0.95
mean = np.mean(data)
se = stats.sem(data)
ci = stats.t.interval(confidence_level, len(data)-1, mean, se)
print(f"95% CI: [{ci[0]:.2f}, {ci[1]:.2f}]")Correlation
# Pearson (linear)
r, p_value = stats.pearsonr(x, y)
# Spearman (rank-based)
rho, p_value = stats.spearmanr(x, y)Distributions
# Normal
x = np.linspace(-3, 3, 100)
pdf = stats.norm.pdf(x, loc=0, scale=1)
# Sampling
samples = np.random.normal(0, 1, 1000)
# Test normality
stat, p_value = stats.shapiro(data)A/B Testing Framework
def ab_test(control, treatment, alpha=0.05):
"""
Run A/B test with statistical significance
Returns: significant (bool), p_value (float)
"""
t_stat, p_value = stats.ttest_ind(control, treatment)
significant = p_value < alpha
improvement = (np.mean(treatment) - np.mean(control)) / np.mean(control) * 100
return {
'significant': significant,
'p_value': p_value,
'improvement': f"{improvement:.2f}%"
}Interpretation
P-value < 0.05: Reject null hypothesis (statistically significant)
P-value >= 0.05: Fail to reject null (not significant)
Common Pitfalls
- Multiple testing without correction
- Small sample sizes
- Ignoring assumptions (normality, independence)
- Confusing correlation with causation
- p-hacking (searching for significance)
Troubleshooting
Common Issues
Problem: Non-normal data for t-test
# Check normality first
stat, p = stats.shapiro(data)
if p < 0.05:
# Use non-parametric alternative
stat, p = stats.mannwhitneyu(group1, group2) # Instead of ttest_indProblem: Multiple comparisons inflating false positives
from statsmodels.stats.multitest import multipletests
# Apply Bonferroni correction
p_values = [0.01, 0.03, 0.04, 0.02, 0.06]
rejected, p_adjusted, _, _ = multipletests(p_values, method='bonferroni')Problem: Underpowered study (sample too small)
from statsmodels.stats.power import TTestIndPower
# Calculate required sample size
power_analysis = TTestIndPower()
sample_size = power_analysis.solve_power(
effect_size=0.5, # Medium effect (Cohen's d)
power=0.8, # 80% power
alpha=0.05 # 5% significance
)
print(f"Required n per group: {sample_size:.0f}")Problem: Heterogeneous variances
# Check with Levene's test
stat, p = stats.levene(group1, group2)
if p < 0.05:
# Use Welch's t-test (default in scipy)
t, p = stats.ttest_ind(group1, group2, equal_var=False)Problem: Outliers affecting results
from scipy.stats import zscore
# Detect outliers (|z| > 3)
z_scores = np.abs(zscore(data))
clean_data = data[z_scores < 3]
# Or use robust statistics
median = np.median(data)
mad = np.median(np.abs(data - median)) # Median Absolute DeviationDebug Checklist
- [ ] Check sample size adequacy (power analysis)
- [ ] Test normality assumption (Shapiro-Wilk)
- [ ] Test homogeneity of variance (Levene's)
- [ ] Check for outliers (z-scores, IQR)
- [ ] Apply multiple testing correction if needed
- [ ] Report effect sizes, not just p-values
# A/B Test Configuration Template
# Statistical testing framework configuration
# Experiment Metadata
experiment:
name: "checkout_flow_optimization"
description: "Test new checkout flow vs current"
owner: "product-team"
start_date: "2024-01-01"
end_date: "2024-01-14"
# Hypothesis
hypothesis:
null: "New checkout flow has no effect on conversion rate"
alternative: "New checkout flow increases conversion rate"
type: "two-tailed" # one-tailed, two-tailed
# Test Configuration
test_config:
# Statistical parameters
significance_level: 0.05 # Alpha (Type I error rate)
power: 0.80 # 1 - Beta (Type II error rate)
minimum_detectable_effect: 0.05 # 5% relative change
# Sample size calculation
baseline_conversion_rate: 0.10 # 10% current conversion
expected_improvement: 0.02 # 2 percentage points
# Test type
test_type: "proportions" # proportions, means, rates
statistical_test: "chi_square" # chi_square, t_test, z_test
# Variants
variants:
- name: "control"
description: "Current checkout flow"
allocation: 0.50 # 50% of traffic
- name: "treatment"
description: "New streamlined checkout"
allocation: 0.50 # 50% of traffic
# Metrics
metrics:
primary:
- name: "conversion_rate"
description: "Proportion of users who complete purchase"
type: "proportion"
success_event: "purchase_completed"
denominator_event: "checkout_started"
secondary:
- name: "average_order_value"
description: "Average purchase amount"
type: "continuous"
- name: "time_to_purchase"
description: "Time from checkout start to completion"
type: "continuous"
unit: "seconds"
guardrail:
- name: "error_rate"
description: "Rate of checkout errors"
type: "proportion"
threshold_type: "upper"
threshold: 0.02 # Alert if errors > 2%
# Segmentation
segmentation:
dimensions:
- "device_type" # mobile, desktop, tablet
- "user_type" # new, returning
- "country"
analyze_segments: true
# Analysis Settings
analysis:
# Correction for multiple comparisons
multiple_comparison_correction: "bonferroni" # bonferroni, holm, fdr
# Confidence intervals
confidence_level: 0.95
# Bayesian analysis (optional)
bayesian:
enabled: true
prior_type: "beta"
prior_alpha: 1
prior_beta: 1
# Sequential analysis
sequential:
enabled: true
check_frequency: "daily"
spending_function: "obrien_fleming"
# Stopping Rules
stopping_rules:
# Early stopping for success
early_success:
enabled: true
threshold: 0.01 # Stop if p-value < 0.01
# Early stopping for futility
futility:
enabled: true
threshold: 0.50 # Stop if effect unlikely
# Safety stopping
safety:
enabled: true
metric: "error_rate"
threshold: 0.05 # Stop if errors > 5%
# Reporting
reporting:
format: "html"
include_visualizations: true
generate_summary: true
recipients:
- "product@company.com"
- "data-science@company.com"
Statistical Test Selection Guide
Test Selection Decision Tree
What type of data do you have?
│
├─► Categorical vs Categorical
│ ├─► 2x2 table → Chi-square or Fisher's exact
│ └─► Larger table → Chi-square test
│
├─► Continuous vs Categorical
│ ├─► 2 groups
│ │ ├─► Normal data → Independent t-test
│ │ └─► Non-normal → Mann-Whitney U
│ │
│ ├─► 2 groups (paired)
│ │ ├─► Normal data → Paired t-test
│ │ └─► Non-normal → Wilcoxon signed-rank
│ │
│ └─► 3+ groups
│ ├─► Normal data → One-way ANOVA
│ └─► Non-normal → Kruskal-Wallis
│
└─► Continuous vs Continuous
├─► Linear relationship
│ ├─► Normal data → Pearson correlation
│ └─► Non-normal → Spearman correlation
│
└─► Prediction → Regression analysisQuick Reference Table
| Scenario | Parametric Test | Non-parametric Alternative |
|---|---|---|
| 2 independent groups | Independent t-test | Mann-Whitney U |
| 2 paired groups | Paired t-test | Wilcoxon signed-rank |
| 3+ independent groups | One-way ANOVA | Kruskal-Wallis |
| 3+ paired groups | Repeated measures ANOVA | Friedman test |
| Correlation | Pearson | Spearman |
| Independence (categorical) | Chi-square | Fisher's exact |
Assumptions Checklist
For Parametric Tests (t-test, ANOVA)
□ Independence of observations
□ Normality (Shapiro-Wilk test p > 0.05)
□ Homogeneity of variance (Levene's test p > 0.05)
□ Continuous dependent variableFor Chi-square Test
□ Independence of observations
□ Expected frequencies ≥ 5 in each cell
□ Mutually exclusive categories
□ Large enough sample (n > 20)Sample Size Guidelines
| Test Type | Minimum per Group | Recommended |
|---|---|---|
| t-test | 12 | 30+ |
| ANOVA | 20 per group | 30+ per group |
| Chi-square | Expected freq ≥ 5 | n > 100 |
| Correlation | 30 | 50+ |
| Regression | 10-20 per predictor | 50+ per predictor |
Effect Size Interpretation
Cohen's d (t-tests)
| Value | Interpretation |
|---|---|
| 0.2 | Small |
| 0.5 | Medium |
| 0.8 | Large |
Eta-squared (ANOVA)
| Value | Interpretation |
|---|---|
| 0.01 | Small |
| 0.06 | Medium |
| 0.14 | Large |
Correlation (r)
| Value | Interpretation |
|---|---|
| 0.1 | Small |
| 0.3 | Medium |
| 0.5 | Large |
P-value Decision Guide
P-value Interpretation:
───────────────────────────────────────
p < 0.001 │ Strong evidence against H0
p < 0.01 │ Very strong evidence
p < 0.05 │ Moderate evidence (typical threshold)
p < 0.10 │ Weak evidence (suggestive)
p ≥ 0.10 │ Little to no evidence
───────────────────────────────────────Multiple Comparison Corrections
| Method | When to Use | How It Works |
|---|---|---|
| Bonferroni | Few comparisons | α / n |
| Holm | Many comparisons | Step-down procedure |
| FDR (Benjamini-Hochberg) | Many comparisons | Controls false discovery rate |
| Tukey HSD | Post-hoc ANOVA | Pairwise comparisons |
Common Mistakes to Avoid
1. p-hacking: Running multiple tests until finding significance 2. Ignoring assumptions: Running parametric tests on non-normal data 3. Small samples: Underpowered studies missing real effects 4. Multiple comparisons: Not adjusting for many tests 5. Confusing statistical and practical significance 6. Correlation ≠ Causation
#!/usr/bin/env python3
"""
Statistical Hypothesis Testing Framework
Comprehensive statistical tests for data science
"""
import numpy as np
from scipy import stats
from typing import Dict, Tuple, Optional, List
from dataclasses import dataclass
from enum import Enum
class TestType(Enum):
ONE_TAILED_LEFT = "one-tailed-left"
ONE_TAILED_RIGHT = "one-tailed-right"
TWO_TAILED = "two-tailed"
@dataclass
class TestResult:
test_name: str
statistic: float
p_value: float
significance_level: float
is_significant: bool
conclusion: str
effect_size: Optional[float] = None
confidence_interval: Optional[Tuple[float, float]] = None
class HypothesisTester:
"""Statistical hypothesis testing framework."""
def __init__(self, alpha: float = 0.05):
self.alpha = alpha
def t_test_independent(self, group1: np.ndarray, group2: np.ndarray,
test_type: TestType = TestType.TWO_TAILED) -> TestResult:
"""
Independent samples t-test.
Compare means of two independent groups.
"""
t_stat, p_value = stats.ttest_ind(group1, group2)
# Adjust p-value for one-tailed tests
if test_type == TestType.ONE_TAILED_LEFT:
p_value = p_value / 2 if t_stat < 0 else 1 - p_value / 2
elif test_type == TestType.ONE_TAILED_RIGHT:
p_value = p_value / 2 if t_stat > 0 else 1 - p_value / 2
# Cohen's d effect size
pooled_std = np.sqrt((np.var(group1) + np.var(group2)) / 2)
cohens_d = (np.mean(group1) - np.mean(group2)) / pooled_std
is_significant = p_value < self.alpha
return TestResult(
test_name="Independent Samples t-test",
statistic=t_stat,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
effect_size=cohens_d,
conclusion=self._generate_conclusion(is_significant, "means")
)
def t_test_paired(self, before: np.ndarray, after: np.ndarray,
test_type: TestType = TestType.TWO_TAILED) -> TestResult:
"""
Paired samples t-test.
Compare means of related samples (before/after).
"""
t_stat, p_value = stats.ttest_rel(before, after)
if test_type == TestType.ONE_TAILED_LEFT:
p_value = p_value / 2 if t_stat < 0 else 1 - p_value / 2
elif test_type == TestType.ONE_TAILED_RIGHT:
p_value = p_value / 2 if t_stat > 0 else 1 - p_value / 2
# Effect size for paired data
diff = before - after
cohens_d = np.mean(diff) / np.std(diff)
is_significant = p_value < self.alpha
return TestResult(
test_name="Paired Samples t-test",
statistic=t_stat,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
effect_size=cohens_d,
conclusion=self._generate_conclusion(is_significant, "means")
)
def chi_square_test(self, observed: np.ndarray) -> TestResult:
"""
Chi-square test for independence.
Test association between categorical variables.
"""
chi2, p_value, dof, expected = stats.chi2_contingency(observed)
# Cramer's V effect size
n = observed.sum()
min_dim = min(observed.shape[0] - 1, observed.shape[1] - 1)
cramers_v = np.sqrt(chi2 / (n * min_dim)) if min_dim > 0 else 0
is_significant = p_value < self.alpha
return TestResult(
test_name="Chi-square Test of Independence",
statistic=chi2,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
effect_size=cramers_v,
conclusion=self._generate_conclusion(is_significant, "association")
)
def anova_one_way(self, *groups) -> TestResult:
"""
One-way ANOVA.
Compare means across multiple groups.
"""
f_stat, p_value = stats.f_oneway(*groups)
# Eta-squared effect size
all_data = np.concatenate(groups)
grand_mean = np.mean(all_data)
ss_between = sum(len(g) * (np.mean(g) - grand_mean)**2 for g in groups)
ss_total = np.sum((all_data - grand_mean)**2)
eta_squared = ss_between / ss_total if ss_total > 0 else 0
is_significant = p_value < self.alpha
return TestResult(
test_name="One-way ANOVA",
statistic=f_stat,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
effect_size=eta_squared,
conclusion=self._generate_conclusion(is_significant, "group means")
)
def mann_whitney_u(self, group1: np.ndarray, group2: np.ndarray) -> TestResult:
"""
Mann-Whitney U test (non-parametric alternative to t-test).
Compare distributions of two independent groups.
"""
u_stat, p_value = stats.mannwhitneyu(group1, group2, alternative='two-sided')
# Effect size (rank-biserial correlation)
n1, n2 = len(group1), len(group2)
effect_size = 1 - (2 * u_stat) / (n1 * n2)
is_significant = p_value < self.alpha
return TestResult(
test_name="Mann-Whitney U Test",
statistic=u_stat,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
effect_size=effect_size,
conclusion=self._generate_conclusion(is_significant, "distributions")
)
def proportion_z_test(self, successes1: int, n1: int,
successes2: int, n2: int) -> TestResult:
"""
Two-proportion z-test.
Compare proportions between two groups (A/B testing).
"""
p1 = successes1 / n1
p2 = successes2 / n2
p_pooled = (successes1 + successes2) / (n1 + n2)
se = np.sqrt(p_pooled * (1 - p_pooled) * (1/n1 + 1/n2))
z_stat = (p1 - p2) / se if se > 0 else 0
p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))
# 95% CI for difference
se_diff = np.sqrt(p1*(1-p1)/n1 + p2*(1-p2)/n2)
ci = (p1 - p2 - 1.96*se_diff, p1 - p2 + 1.96*se_diff)
is_significant = p_value < self.alpha
return TestResult(
test_name="Two-Proportion Z-test",
statistic=z_stat,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
effect_size=p1 - p2,
confidence_interval=ci,
conclusion=self._generate_conclusion(is_significant, "proportions")
)
def normality_test(self, data: np.ndarray) -> TestResult:
"""
Shapiro-Wilk test for normality.
Check if data follows normal distribution.
"""
# Use Shapiro-Wilk for n < 5000, D'Agostino-Pearson otherwise
if len(data) < 5000:
stat, p_value = stats.shapiro(data)
test_name = "Shapiro-Wilk Normality Test"
else:
stat, p_value = stats.normaltest(data)
test_name = "D'Agostino-Pearson Normality Test"
is_significant = p_value < self.alpha
# Note: for normality, significant = NOT normal
conclusion = (
"Data is NOT normally distributed (reject normality)"
if is_significant else
"Data appears normally distributed (fail to reject normality)"
)
return TestResult(
test_name=test_name,
statistic=stat,
p_value=p_value,
significance_level=self.alpha,
is_significant=is_significant,
conclusion=conclusion
)
def _generate_conclusion(self, is_significant: bool, comparison_type: str) -> str:
"""Generate human-readable conclusion."""
if is_significant:
return f"Statistically significant difference in {comparison_type} (p < {self.alpha})"
else:
return f"No statistically significant difference in {comparison_type} (p >= {self.alpha})"
def calculate_sample_size(baseline_rate: float, mde: float,
alpha: float = 0.05, power: float = 0.8) -> int:
"""
Calculate required sample size per group for A/B test.
Args:
baseline_rate: Current conversion rate
mde: Minimum detectable effect (absolute)
alpha: Significance level
power: Statistical power
"""
from scipy.stats import norm
p1 = baseline_rate
p2 = baseline_rate + mde
p_avg = (p1 + p2) / 2
z_alpha = norm.ppf(1 - alpha / 2)
z_beta = norm.ppf(power)
n = (2 * p_avg * (1 - p_avg) * (z_alpha + z_beta)**2) / (p2 - p1)**2
return int(np.ceil(n))
def main():
"""Demo statistical tests."""
print("Statistical Hypothesis Testing Demo")
print("=" * 50)
tester = HypothesisTester(alpha=0.05)
# Example: A/B Test (proportion comparison)
print("\n1. A/B Test Example:")
print("-" * 30)
# Control: 100 conversions out of 1000
# Treatment: 120 conversions out of 1000
result = tester.proportion_z_test(100, 1000, 120, 1000)
print(f"Test: {result.test_name}")
print(f"Z-statistic: {result.statistic:.4f}")
print(f"P-value: {result.p_value:.4f}")
print(f"Effect size: {result.effect_size:.4f}")
print(f"95% CI: [{result.confidence_interval[0]:.4f}, {result.confidence_interval[1]:.4f}]")
print(f"Conclusion: {result.conclusion}")
# Example: Comparing two groups
print("\n2. T-test Example:")
print("-" * 30)
group_a = np.random.normal(100, 15, 50)
group_b = np.random.normal(110, 15, 50)
result = tester.t_test_independent(group_a, group_b)
print(f"Test: {result.test_name}")
print(f"T-statistic: {result.statistic:.4f}")
print(f"P-value: {result.p_value:.4f}")
print(f"Cohen's d: {result.effect_size:.4f}")
print(f"Conclusion: {result.conclusion}")
# Sample size calculation
print("\n3. Sample Size Calculation:")
print("-" * 30)
n = calculate_sample_size(baseline_rate=0.10, mde=0.02)
print(f"Required sample size per group: {n:,}")
print(f"(For detecting 2% absolute lift from 10% baseline)")
if __name__ == '__main__':
main()
Related skills
FAQ
What does statistical-analysis do?
statistical-analysis is a Claude Code skill for ai & agent building.
When should I use statistical-analysis?
When you need to helps with ai & agent building tasks., or when statistical-analysis is a claude code skill for ai & agent building.
What are the main capabilities?
statistical-analysis; AI & Agent Building; AI-coding skill.