
Data Analysis
- 1.5k installs
- 255 repo stars
- Updated February 27, 2026
- lingzhi227/agent-research-skills
data-analysis is an agent skill that generates statistically reviewed analysis code with p-values, effect sizes, and confidence intervals for experimental research data.
About
The data-analysis skill produces rigorous statistical analysis code for research papers from CSV, JSON, pickle, or experiment log inputs plus a stated hypothesis. It structures generated Python with import, load, dataset preparation, descriptive statistics, preprocessing, analysis, and pickle export sections. A four-round review cycle checks code flaws, data handling, per-table sanity, and cross-table consistency using prompts from bundled reference files. Helper scripts stat_summary.py and format_pvalue.py recommend tests by data type, run group comparisons, and format p-values as stars or LaTeX. Allowed packages are pandas, numpy, scipy, statsmodels, sklearn, and pickle. Test selection covers t-tests, Mann-Whitney, ANOVA, chi-square, correlation, and regression variants matched to variable types. Rules require p-values on every test, confounder control, string-based column access, and never hallucinating results. Downstream skills include table-generation, figure-generation, and backward-traceability. Use when developers need reproducible analysis code and reviewed outputs for paper experiments.
- Four-round review covers code flaws, data handling, per-table checks, and cross-table consistency.
- stat_summary.py recommends tests, compares groups, and outputs effect sizes with significance stars.
- Structured code sections from IMPORT through SAVE ADDITIONAL RESULTS for reproducible pipelines.
- Test selection table maps data types to t-tests, Mann-Whitney, ANOVA, chi-square, and regression.
- Every nominal result must include uncertainty via CI, STD, or p-value per skill rules.
Data Analysis by the numbers
- 1,532 all-time installs (skills.sh)
- +45 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #154 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
data-analysis capabilities & compatibility
- Capabilities
- four round statistical code review · automated test recommendation by data type · group comparison with effect sizes · p value formatting to stars or latex · structured reproducible analysis sections
- Use cases
- research · data analysis · documentation
What data-analysis says it does
Generate statistical analysis code with 4-round review.
Every nominal value must have uncertainty (CI, STD, or p-value)
npx skills add https://github.com/lingzhi227/agent-research-skills --skill data-analysisAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.5k |
|---|---|
| repo stars | ★ 255 |
| Security audit | 2 / 3 scanners passed |
| Last updated | February 27, 2026 |
| Repository | lingzhi227/agent-research-skills ↗ |
How do I write correct statistical tests and reviewed analysis code for experimental results in a research paper?
Generate statistical analysis code with four-round review for experimental datasets, hypothesis tests, and publication-ready p-values and effect sizes.
Who is it for?
Developers analyzing experimental datasets for papers who need test selection, multi-round code review, and formatted significance reporting.
Skip if: Skip for raw data collection pipelines or visualization-only tasks without hypothesis testing.
When should I use this skill?
User analyzes experimental data for a paper, needs statistical comparisons, or asks for p-values and effect sizes from CSV results.
What you get
Reviewed Python analysis code with appropriate tests, formatted p-values, effect sizes, and consistency-checked result tables.
- Review round reports
- Flagged calculation list
- Statistical flaw summary
By the numbers
- Implements a 4-round structured code review system extracted from data-to-paper and AgentLaboratory
Files
Data Analysis
Generate rigorous statistical analysis code with multi-round review.
Input
$0— Data source (CSV, JSON, pickle, or experiment logs)$1— Research goal or hypothesis to test
References
- 4-round code review prompts:
~/.claude/skills/data-analysis/references/review-prompts.md
Scripts
Statistical summary and comparison
python ~/.claude/skills/data-analysis/scripts/stat_summary.py --input results.csv --compare method --metric accuracy --output summary.json
python ~/.claude/skills/data-analysis/scripts/stat_summary.py --input results.csv --describeDetects data types, recommends tests, runs comparisons, outputs effect sizes and significance stars. Requires numpy, scipy.
Format p-values
python ~/.claude/skills/data-analysis/scripts/format_pvalue.py --values "0.001 0.05 0.23" --format stars
python ~/.claude/skills/data-analysis/scripts/format_pvalue.py --csv results.csv --column pvalue --format latexFormats p-values with stars, LaTeX notation, or plain text. Stdlib-only.
Workflow
Step 1: Generate Analysis Code
Structure the code with these sections: 1. # IMPORT — pandas, numpy, scipy, statsmodels, sklearn 2. # LOAD DATA — Load from original data files 3. # DATASET PREPARATIONS — Missing values, units, exclusion criteria 4. # DESCRIPTIVE STATISTICS — Summary tables if needed 5. # PREPROCESSING — Dummy variables, normalization 6. # ANALYSIS — Statistical tests per hypothesis 7. # SAVE ADDITIONAL RESULTS — Extra results to pickle
Step 2: 4-Round Code Review
1. Round 1 — Code Flaws: Mathematical/statistical errors, wrong calculations, trivial tests 2. Round 2 — Data Handling: Missing values, units, preprocessing, test choice 3. Round 3 — Per-Table: Sensible values, measures of uncertainty, missing data 4. Round 4 — Cross-Table: Completeness, consistency, missing variables
Step 3: Produce Results
- Every nominal value must have uncertainty (CI, STD, or p-value)
- Statistical tests must be appropriate for the data type
- Results must match actual data — never hallucinate
Allowed Packages
pandas, numpy, scipy, statsmodels, sklearn, pickle
Statistical Test Selection
| Data Type | Test |
|---|---|
| Two groups, normal | Independent t-test |
| Two groups, non-normal | Mann-Whitney U |
| Paired samples | Paired t-test / Wilcoxon |
| Multiple groups | ANOVA / Kruskal-Wallis |
| Categorical | Chi-square / Fisher's exact |
| Correlation | Pearson / Spearman |
| Regression | OLS / Logistic / Mixed effects |
Rules
- Always report p-values for statistical tests
- Account for relevant confounding variables
- Use inherent package functionality (e.g.,
formula = "y ~ a * b"for interactions) - Do not manually implement available statistical functions
- Access dataframes using string-based column names, not integer indices
Related Skills
- Upstream: experiment-code, experiment-design
- Downstream: table-generation, figure-generation, backward-traceability
- See also: math-reasoning
Data Analysis Review Prompts
Extracted from data-to-paper (hypothesis_testing/coding/analysis/coding.py) and AgentLaboratory.
4-Round Code Review System (data-to-paper)
Round 1: Fundamental Code Flaws
### CHECK FOR FUNDAMENTAL FLAWS:
Check for any fundamental mathematical or statistical flaws in the code.
### CHECK FOR WRONG CALCULATIONS:
Explicitly list all key calculations and assess them.
### CHECK FOR MATH TRIVIALITIES:
Check for any mathematically trivial assessments / statistical tests.
For example, testing whether a value is different from zero when it is
defined as a sum of positive values.
### OTHER ISSUES:
Any other issues you find in the code.Round 2: Data Handling Issues
### DATASET PREPARATIONS:
- Missing values: Are missing values handled correctly?
- Units: Are units consistent and correctly converted?
- Data restriction: Is data appropriately filtered/restricted?
### DESCRIPTIVE STATISTICS:
Check for issues in descriptive statistics calculations.
### PREPROCESSING:
Review data preprocessing steps:
- Normalization / standardization
- Feature encoding
- Train/test split methodology
### ANALYSIS:
Check data analysis issues:
- Correct statistical test selection
- Assumptions met (normality, independence, etc.)
- Multiple comparisons correction
### STATISTICAL TESTS:
Check choice and implementation of statistical tests:
- Is the test appropriate for the data type?
- Are assumptions validated?
- Are p-values correctly computed and interpreted?Round 3: Per-Table Individual Review
### SENSIBLE NUMERIC VALUES:
Check each numeric value in the table:
- Are values within expected ranges?
- Do percentages sum to 100% where expected?
- Are decimal places appropriate?
### MEASURES OF UNCERTAINTY:
Does the table report measures of uncertainty?
- p-values for statistical tests
- Confidence intervals for estimates
- Standard deviations for means
### MISSING DATA:
Are we missing key variables or important results?
### OTHER ISSUES:
Any other issues you find in the table.Note: This round runs individually for each output file (df_.pkl).*
Round 4: Cross-Table Completeness
### COMPLETENESS OF TABLES:
Does the code create all needed results for the hypothesis testing plan?
### CONSISTENCY ACROSS TABLES:
Are tables consistent in:
- Variable naming conventions
- Measures of uncertainty reported
- Decimal precision
- Statistical test choices
### MISSING DATA:
Are we missing key variables or measures of uncertainty
that should be reported for a complete analysis?Allowed Packages Whitelist (data-to-paper)
ALLOWED_PACKAGES = [
'pandas',
'numpy',
'scipy',
'statsmodels',
'sklearn',
'pingouin', # For ANOVA and post-hoc tests
'matplotlib', # For diagnostic plots only
]Statistical Test Selection Guide
Select the appropriate statistical test based on:
| Data Type | Groups | Test |
|-----------|--------|------|
| Continuous, normal, 2 groups | Independent | Independent t-test |
| Continuous, normal, 2 groups | Paired | Paired t-test |
| Continuous, non-normal, 2 groups | Independent | Mann-Whitney U |
| Continuous, normal, 3+ groups | Independent | One-way ANOVA |
| Continuous, non-normal, 3+ groups | Independent | Kruskal-Wallis |
| Categorical, 2 variables | Independent | Chi-square test |
| Continuous, 2 variables | Correlation | Pearson/Spearman |
| Binary outcome | Multiple predictors | Logistic regression |
Always check assumptions before applying parametric tests:
1. Normality (Shapiro-Wilk test)
2. Homogeneity of variance (Levene's test)
3. Independence of observationsResults Interpretation Dialogue (AgentLaboratory)
Postdoc guides PhD to extract insights:
1. "What are the key findings from the results?"
2. "Are there any surprising or unexpected results?"
3. "How do results compare to baselines?"
4. "What is the statistical significance of improvements?"
5. "Are there any failure cases or limitations?"
6. "What patterns do you observe across datasets?"#!/usr/bin/env python3
"""Format p-values for academic papers.
Formats p-values with proper precision, significance stars,
and LaTeX-compatible output.
Self-contained: uses only stdlib.
Extracted from data-to-paper's pvalue.py formatting utilities.
Usage:
python format_pvalue.py --values "0.001 0.05 0.23" --format stars
python format_pvalue.py --values "0.0001 0.03 0.5" --format latex
python format_pvalue.py --values "1e-8 0.01 0.1" --format text
python format_pvalue.py --csv results.csv --column pvalue --format stars
"""
import argparse
import csv
import json
import sys
P_VALUE_MIN = 1e-6
DEFAULT_LEVELS = (0.05, 0.01, 0.001)
def format_p_value(p: float, min_val: float = P_VALUE_MIN,
smaller_than: str = "<") -> str:
"""Format a p-value to a string with appropriate precision."""
if not isinstance(p, (int, float)):
return str(p)
if p < 0 or p > 1:
return f"invalid({p})"
if p >= min_val:
return f"{p:.3g}"
return f"{smaller_than}{min_val}"
def format_p_value_latex(p: float, min_val: float = P_VALUE_MIN) -> str:
"""Format a p-value for LaTeX output."""
if p >= min_val:
return f"${p:.3g}$"
return f"$<${min_val}"
def p_to_stars(p: float, levels: tuple = DEFAULT_LEVELS) -> str:
"""Convert p-value to significance stars.
Default levels: * p<0.05, ** p<0.01, *** p<0.001
"""
if p < levels[2]:
return "***"
if p < levels[1]:
return "**"
if p < levels[0]:
return "*"
return "ns"
def stars_legend(levels: tuple = DEFAULT_LEVELS) -> str:
"""Generate a legend string for significance stars."""
parts = [f"ns p >= {levels[0]}"]
symbols = ["*", "**", "***"]
for i, level in enumerate(levels):
parts.append(f"{symbols[i]} p < {level}")
return ", ".join(parts)
def format_comparison(name1: str, name2: str, p: float,
fmt: str = "text") -> str:
"""Format a comparison result with p-value."""
if fmt == "stars":
return f"{name1} vs {name2}: p={format_p_value(p)} {p_to_stars(p)}"
elif fmt == "latex":
star = p_to_stars(p)
pstr = format_p_value_latex(p)
return f"{name1} vs {name2}: {pstr} {star}"
else:
return f"{name1} vs {name2}: p={format_p_value(p)}"
def main():
parser = argparse.ArgumentParser(description="Format p-values for academic papers")
parser.add_argument("--values", help="Space-separated p-values")
parser.add_argument("--csv", help="CSV file with p-values")
parser.add_argument("--column", default="pvalue", help="Column name in CSV (default: pvalue)")
parser.add_argument("--format", choices=["text", "stars", "latex", "json"],
default="text", help="Output format (default: text)")
parser.add_argument("--levels", help="Significance levels (comma-separated, default: 0.05,0.01,0.001)")
parser.add_argument("--output", "-o", help="Output file")
args = parser.parse_args()
levels = DEFAULT_LEVELS
if args.levels:
levels = tuple(float(x) for x in args.levels.split(","))
p_values = []
if args.values:
for v in args.values.split():
try:
p_values.append(float(v))
except ValueError:
print(f"Warning: skipping invalid value '{v}'", file=sys.stderr)
elif args.csv:
with open(args.csv, encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
try:
p_values.append(float(row[args.column]))
except (ValueError, KeyError):
pass
else:
print("Error: specify --values or --csv", file=sys.stderr)
sys.exit(1)
if not p_values:
print("No valid p-values found.", file=sys.stderr)
sys.exit(1)
results = []
for p in p_values:
entry = {"p_value": p}
entry["formatted"] = format_p_value(p)
entry["stars"] = p_to_stars(p, levels)
entry["latex"] = format_p_value_latex(p)
results.append(entry)
output_lines = []
if args.format == "json":
output_lines.append(json.dumps(results, indent=2))
elif args.format == "stars":
for r in results:
output_lines.append(f"p={r['formatted']} {r['stars']}")
output_lines.append(f"\nLegend: {stars_legend(levels)}")
elif args.format == "latex":
for r in results:
output_lines.append(f"{r['latex']} {r['stars']}")
else:
for r in results:
output_lines.append(f"p = {r['formatted']}")
text = "\n".join(output_lines) + "\n"
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(text)
print(f"Written to {args.output}", file=sys.stderr)
else:
sys.stdout.write(text)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Statistical summary and comparison of experimental results.
Takes experiment results in CSV/JSON, detects data types, recommends
statistical tests, runs comparisons, and outputs formatted results.
Requires: numpy, scipy
Usage:
python stat_summary.py --input results.csv --compare method --metric accuracy --output summary.json
python stat_summary.py --input results.json --compare model --metric f1_score
python stat_summary.py --input results.csv --describe
"""
import argparse
import csv
import json
import math
import os
import sys
try:
import numpy as np
from scipy import stats
except ImportError:
print("Error: numpy and scipy required. Install: pip install numpy scipy", file=sys.stderr)
sys.exit(1)
def load_data(path: str) -> list[dict]:
"""Load data from CSV or JSON."""
ext = os.path.splitext(path)[1].lower()
if ext == ".csv":
with open(path, encoding="utf-8") as f:
reader = csv.DictReader(f)
return list(reader)
elif ext == ".json":
with open(path, encoding="utf-8") as f:
data = json.load(f)
if isinstance(data, list):
return data
raise ValueError("JSON must be a list of records")
else:
raise ValueError(f"Unsupported format: {ext}")
def detect_numeric_columns(data: list[dict]) -> list[str]:
"""Detect which columns contain numeric data."""
if not data:
return []
numeric = []
for key in data[0].keys():
try:
vals = [float(row[key]) for row in data if row.get(key, "") != ""]
if len(vals) > len(data) * 0.5:
numeric.append(key)
except (ValueError, TypeError):
pass
return numeric
def get_column_values(data: list[dict], col: str) -> list[float]:
"""Extract numeric values from a column."""
vals = []
for row in data:
try:
vals.append(float(row[col]))
except (ValueError, TypeError, KeyError):
pass
return vals
def describe_column(values: list[float]) -> dict:
"""Compute descriptive statistics for a numeric column."""
arr = np.array(values)
return {
"count": len(arr),
"mean": float(np.mean(arr)),
"std": float(np.std(arr, ddof=1)) if len(arr) > 1 else 0.0,
"min": float(np.min(arr)),
"q25": float(np.percentile(arr, 25)),
"median": float(np.median(arr)),
"q75": float(np.percentile(arr, 75)),
"max": float(np.max(arr)),
}
def recommend_test(groups: list[list[float]]) -> str:
"""Recommend a statistical test based on the data."""
n_groups = len(groups)
if n_groups < 2:
return "none"
# Check normality (Shapiro-Wilk for each group)
all_normal = True
for g in groups:
if len(g) < 3:
all_normal = False
break
if len(g) <= 5000:
_, p = stats.shapiro(g)
if p < 0.05:
all_normal = False
break
if n_groups == 2:
# Check if paired (same length)
if len(groups[0]) == len(groups[1]):
return "paired_ttest" if all_normal else "wilcoxon"
return "independent_ttest" if all_normal else "mann_whitney"
else:
return "anova" if all_normal else "kruskal_wallis"
def run_comparison(groups: dict[str, list[float]], test: str) -> dict:
"""Run a statistical comparison between groups."""
group_names = list(groups.keys())
group_values = list(groups.values())
result = {
"test": test,
"groups": {name: describe_column(vals) for name, vals in groups.items()},
}
if test == "independent_ttest" and len(group_values) == 2:
stat, p = stats.ttest_ind(group_values[0], group_values[1])
result["statistic"] = float(stat)
result["p_value"] = float(p)
elif test == "paired_ttest" and len(group_values) == 2:
stat, p = stats.ttest_rel(group_values[0], group_values[1])
result["statistic"] = float(stat)
result["p_value"] = float(p)
elif test == "mann_whitney" and len(group_values) == 2:
stat, p = stats.mannwhitneyu(group_values[0], group_values[1], alternative='two-sided')
result["statistic"] = float(stat)
result["p_value"] = float(p)
elif test == "wilcoxon" and len(group_values) == 2:
stat, p = stats.wilcoxon(group_values[0], group_values[1])
result["statistic"] = float(stat)
result["p_value"] = float(p)
elif test == "anova":
stat, p = stats.f_oneway(*group_values)
result["statistic"] = float(stat)
result["p_value"] = float(p)
elif test == "kruskal_wallis":
stat, p = stats.kruskal(*group_values)
result["statistic"] = float(stat)
result["p_value"] = float(p)
# Effect size (Cohen's d for two groups)
if len(group_values) == 2:
n1, n2 = len(group_values[0]), len(group_values[1])
m1, m2 = np.mean(group_values[0]), np.mean(group_values[1])
s1, s2 = np.std(group_values[0], ddof=1), np.std(group_values[1], ddof=1)
pooled_std = math.sqrt(((n1 - 1) * s1**2 + (n2 - 1) * s2**2) / (n1 + n2 - 2))
if pooled_std > 0:
result["cohens_d"] = float((m1 - m2) / pooled_std)
# Significance stars
if "p_value" in result:
p = result["p_value"]
if p < 0.001:
result["significance"] = "***"
elif p < 0.01:
result["significance"] = "**"
elif p < 0.05:
result["significance"] = "*"
else:
result["significance"] = "ns"
return result
def pairwise_comparisons(groups: dict[str, list[float]]) -> list[dict]:
"""Run pairwise comparisons between all groups."""
names = list(groups.keys())
results = []
for i in range(len(names)):
for j in range(i + 1, len(names)):
pair = {names[i]: groups[names[i]], names[j]: groups[names[j]]}
test = recommend_test(list(pair.values()))
comp = run_comparison(pair, test)
comp["pair"] = [names[i], names[j]]
results.append(comp)
return results
def main():
parser = argparse.ArgumentParser(description="Statistical summary of experimental results")
parser.add_argument("--input", required=True, help="Input file (.csv or .json)")
parser.add_argument("--compare", help="Column to group by for comparison")
parser.add_argument("--metric", help="Metric column to compare")
parser.add_argument("--describe", action="store_true", help="Show descriptive statistics only")
parser.add_argument("--pairwise", action="store_true", help="Run all pairwise comparisons")
parser.add_argument("--output", "-o", help="Output JSON file")
args = parser.parse_args()
data = load_data(args.input)
if not data:
print("No data loaded.", file=sys.stderr)
sys.exit(1)
numeric_cols = detect_numeric_columns(data)
if args.describe:
result = {"columns": {}}
for col in numeric_cols:
vals = get_column_values(data, col)
result["columns"][col] = describe_column(vals)
print(f"Descriptive statistics for {len(numeric_cols)} numeric columns:", file=sys.stderr)
elif args.compare and args.metric:
# Group by compare column
groups = {}
for row in data:
group = str(row.get(args.compare, "unknown"))
val = row.get(args.metric)
try:
val = float(val)
except (ValueError, TypeError):
continue
groups.setdefault(group, []).append(val)
if len(groups) < 2:
print(f"Need at least 2 groups, found {len(groups)}", file=sys.stderr)
sys.exit(1)
test = recommend_test(list(groups.values()))
print(f"Groups: {list(groups.keys())}", file=sys.stderr)
print(f"Recommended test: {test}", file=sys.stderr)
result = run_comparison(groups, test)
if args.pairwise and len(groups) > 2:
result["pairwise"] = pairwise_comparisons(groups)
else:
print("Error: specify --describe or both --compare and --metric", file=sys.stderr)
sys.exit(1)
output = json.dumps(result, indent=2, ensure_ascii=False)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output)
print(f"Written to {args.output}", file=sys.stderr)
else:
print(output)
if __name__ == "__main__":
main()
Related skills
Forks & variants (2)
Data Analysis has 2 known copies in the catalog totaling 20 installs. They canonicalize to this original listing.
- lingzhi227 - 19 installs
- lingzhi227 - 1 installs
How it compares
Use data-analysis for multi-round statistical code audits; use generic linters when you only need syntax or style checks.
FAQ
What does data-analysis produce?
Structured Python analysis code with statistical tests, four-round review, and formatted p-values plus effect sizes for research outputs.
When should I use data-analysis?
When generating or reviewing statistical analysis code for experimental data with hypotheses to test for publication.
Is data-analysis safe to install?
Review the Security Audits panel on this page before installing in production.