Senior data scientist
World-class senior data scientist skill specialising in statistical modeling, experiment design, causal inference, and predictive analytics.
How to use it
Claude Code
- Run the line below. It pulls the whole folder into
~/.claude/skills/senior-data-scientist, including the files SKILL.md points to. - Describe your job in plain words. Claude Code follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit alirezarezvani/claude-skills/engineering-team/skills/senior-data-scientist#main ~/.claude/skills/senior-data-scientistFor one project only, change the path to .claude/skills/senior-data-scientist. This skill also uses experiment_spec.json, experiment_design.json, raw_features.json, features.json, model_predictions.json, evaluation.json — copying SKILL.md alone won't be enough. See the folder on GitHub.
Claude (web or desktop app)
- On this page open ⋯ → Download .md.
- Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
- Pick the file and Save. Claude shows the name and description and runs a security scan.
- Check the skill is switched on.
- Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
- ChatGPT: make a Project and paste it into Instructions.
- Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
- Check which app you pasted it into — the steps above name the right one.
- Some skills need the paid tier of Claude or ChatGPT.
Paste into Claude, ChatGPT or Cursor.
Source of Senior data scientist
Show the full text218 lines
| name | description |
|---|---|
| senior-data-scientist | World-class senior data scientist skill specialising in statistical modeling, experiment design, causal inference, and predictive analytics. Covers A/B testing (sample sizing, two-proportion z-tests, Bonferroni correction), difference-in-differences, feature engineering pipelines (Scikit-learn, XGBoost), cross-validated model evaluation (AUC-ROC, AUC-PR, SHAP), and MLflow experiment tracking — using Python (NumPy, Pandas, Scikit-learn), R, and SQL. Use when designing or analysing controlled experiments, building and evaluating classification or regression models, performing causal analysis on observational data, engineering features for structured tabular datasets, or translating statistical findings into data-driven business decisions. |
Senior Data Scientist
World-class senior data scientist skill for production-grade AI/ML/Data systems.
Core Workflows
1. Design an A/B Test
import numpy as np
from scipy import stats
def calculate_sample_size(baseline_rate, mde, alpha=0.05, power=0.8):
"""
Calculate required sample size per variant.
baseline_rate: current conversion rate (e.g. 0.10)
mde: minimum detectable effect (relative, e.g. 0.05 = 5% lift)
"""
p1 = baseline_rate
p2 = baseline_rate * (1 + mde)
effect_size = abs(p2 - p1) / np.sqrt((p1 * (1 - p1) + p2 * (1 - p2)) / 2)
z_alpha = stats.norm.ppf(1 - alpha / 2)
z_beta = stats.norm.ppf(power)
n = ((z_alpha + z_beta) / effect_size) ** 2
return int(np.ceil(n))
def analyze_experiment(control, treatment, alpha=0.05):
"""
Run two-proportion z-test and return structured results.
control/treatment: dicts with 'conversions' and 'visitors'.
"""
p_c = control["conversions"] / control["visitors"]
p_t = treatment["conversions"] / treatment["visitors"]
pooled = (control["conversions"] + treatment["conversions"]) / (control["visitors"] + treatment["visitors"])
se = np.sqrt(pooled * (1 - pooled) * (1 / control["visitors"] + 1 / treatment["visitors"]))
z = (p_t - p_c) / se
p_value = 2 * (1 - stats.norm.cdf(abs(z)))
ci_low = (p_t - p_c) - stats.norm.ppf(1 - alpha / 2) * se
ci_high = (p_t - p_c) + stats.norm.ppf(1 - alpha / 2) * se
return {
"lift": (p_t - p_c) / p_c,
"p_value": p_value,
"significant": p_value < alpha,
"ci_95": (ci_low, ci_high),
}
# --- Experiment checklist ---
# 1. Define ONE primary metric and pre-register secondary metrics.
# 2. Calculate sample size BEFORE starting: calculate_sample_size(0.10, 0.05)
# 3. Randomise at the user (not session) level to avoid leakage.
# 4. Run for at least 1 full business cycle (typically 2 weeks).
# 5. Check for sample ratio mismatch: abs(n_control - n_treatment) / expected < 0.01
# 6. Analyze with analyze_experiment() and report lift + CI, not just p-value.
# 7. Apply Bonferroni correction if testing multiple metrics: alpha / n_metrics
2. Build a Feature Engineering Pipeline
import pandas as pd
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
def build_feature_pipeline(numeric_cols, categorical_cols, date_cols=None):
"""
Returns a fitted-ready ColumnTransformer for structured tabular data.
"""
numeric_pipeline = Pipeline([
("impute", SimpleImputer(strategy="median")),
("scale", StandardScaler()),
])
categorical_pipeline = Pipeline([
("impute", SimpleImputer(strategy="most_frequent")),
("encode", OneHotEncoder(handle_unknown="ignore", sparse_output=False)),
])
transformers = [
("num", numeric_pipeline, numeric_cols),
("cat", categorical_pipeline, categorical_cols),
]
return ColumnTransformer(transformers, remainder="drop")
def add_time_features(df, date_col):
"""Extract cyclical and lag features from a datetime column."""
df = df.copy()
df[date_col] = pd.to_datetime(df[date_col])
df["dow_sin"] = np.sin(2 * np.pi * df[date_col].dt.dayofweek / 7)
df["dow_cos"] = np.cos(2 * np.pi * df[date_col].dt.dayofweek / 7)
df["month_sin"] = np.sin(2 * np.pi * df[date_col].dt.month / 12)
df["month_cos"] = np.cos(2 * np.pi * df[date_col].dt.month / 12)
df["is_weekend"] = (df[date_col].dt.dayofweek >= 5).astype(int)
return df
# --- Feature engineering checklist ---
# 1. Never fit transformers on the full dataset — fit on train, transform test.
# 2. Log-transform right-skewed numeric features before scaling.
# 3. For high-cardinality categoricals (>50 levels), use target encoding or embeddings.
# 4. Generate lag/rolling features BEFORE the train/test split to avoid leakage.
# 5. Document each feature's business meaning alongside its code.
3. Train, Evaluate, and Select a Prediction Model
from sklearn.model_selection import StratifiedKFold, cross_validate
from sklearn.metrics import make_scorer, roc_auc_score, average_precision_score
import xgboost as xgb
import mlflow
SCORERS = {
"roc_auc": make_scorer(roc_auc_score, needs_proba=True),
"avg_prec": make_scorer(average_precision_score, needs_proba=True),
}
def evaluate_model(model, X, y, cv=5):
"""
Cross-validate and return mean ± std for each scorer.
Use StratifiedKFold for classification to preserve class balance.
"""
cv_results = cross_validate(
model, X, y,
cv=StratifiedKFold(n_splits=cv, shuffle=True, random_state=42),
scoring=SCORERS,
return_train_score=True,
)
summary = {}
for metric in SCORERS:
test_scores = cv_results[f"test_{metric}"]
summary[metric] = {"mean": test_scores.mean(), "std": test_scores.std()}
# Flag overfitting: large gap between train and test score
train_mean = cv_results[f"train_{metric}"].mean()
summary[metric]["overfit_gap"] = train_mean - test_scores.mean()
return summary
def train_and_log(model, X_train, y_train, X_test, y_test, run_name):
"""Train model and log all artefacts to MLflow."""
with mlflow.start_run(run_name=run_name):
model.fit(X_train, y_train)
proba = model.predict_proba(X_test)[:, 1]
metrics = {
"roc_auc": roc_auc_score(y_test, proba),
"avg_prec": average_precision_score(y_test, proba),
}
mlflow.log_params(model.get_params())
mlflow.log_metrics(metrics)
mlflow.sklearn.log_model(model, "model")
return metrics
# --- Model evaluation checklist ---
# 1. Always report AUC-PR alongside AUC-ROC for imbalanced datasets.
# 2. Check overfit_gap > 0.05 as a warning sign of overfitting.
# 3. Calibrate probabilities (Platt scaling / isotonic) before production use.
# 4. Compute SHAP values to validate feature importance makes business sense.
# 5. Run a baseline (e.g. DummyClassifier) and verify the model beats it.
# 6. Log every run to MLflow — never rely on notebook output for comparison.
4. Causal Inference: Difference-in-Differences
import statsmodels.formula.api as smf
def diff_in_diff(df, outcome, treatment_col, post_col, controls=None):
"""
Estimate ATT via OLS DiD with optional covariates.
df must have: outcome, treatment_col (0/1), post_col (0/1).
Returns the interaction coefficient (treatment × post) and its p-value.
"""
covariates = " + ".join(controls) if controls else ""
formula = (
f"{outcome} ~ {treatment_col} * {post_col}"
+ (f" + {covariates}" if covariates else "")
)
result = smf.ols(formula, data=df).fit(cov_type="HC3")
interaction = f"{treatment_col}:{post_col}"
return {
"att": result.params[interaction],
"p_value": result.pvalues[interaction],
"ci_95": result.conf_int().loc[interaction].tolist(),
"summary": result.summary(),
}
# --- Causal inference checklist ---
# 1. Validate parallel trends in pre-period before trusting DiD estimates.
# 2. Use HC3 robust standard errors to handle heteroskedasticity.
# 3. For panel data, cluster SEs at the unit level (add groups= param to fit).
# 4. Consider propensity score matching if groups differ at baseline.
# 5. Report the ATT with confidence interval, not just statistical significance.
Reference Documentation
- Statistical Methods:
references/statistical_methods_advanced.md - Experiment Design Frameworks:
references/experiment_design_frameworks.md - Feature Engineering Patterns:
references/feature_engineering_patterns.md
Common Commands
# Testing & linting
python -m pytest tests/ -v --cov=src/
python -m black src/ && python -m pylint src/
# Bundled pipeline scaffolds (stdlib runners — extend the process() body with project logic)
python3 scripts/experiment_designer.py --input experiment_spec.json --output experiment_design.json
python3 scripts/feature_engineering_pipeline.py --input raw_features.json --output features.json
python3 scripts/model_evaluation_suite.py --input model_predictions.json --output evaluation.json
# Each prints a JSON run report ({status, processed_items, start/end_time}); any status other
# than "completed" means the stage failed — fix before moving to the next pipeline stage.
| 1 | |
| 2 | name "senior-data-scientist" |
| 3 | description World-class senior data scientist skill specialising in statistical modeling, experiment design, causal inference, and predictive analytics. Covers A/B testing (sample sizing, two-proportion z-tests, Bonferroni correction), difference-in-differences, feature engineering pipelines (Scikit-learn, XGBoost), cross-validated model evaluation (AUC-ROC, AUC-PR, SHAP), and MLflow experiment tracking — using Python (NumPy, Pandas, Scikit-learn), R, and SQL. Use when designing or analysing controlled experiments, building and evaluating classification or regression models, performing causal analysis on observational data, engineering features for structured tabular datasets, or translating statistical findings into data-driven business decisions. |
| 4 | |
| 5 | |
| 6 | # Senior Data Scientist |
| 7 | |
| 8 | World-class senior data scientist skill for production-grade AI/ML/Data systems. |
| 9 | |
| 10 | ## Core Workflows |
| 11 | |
| 12 | ### 1. Design an A/B Test |
| 13 | |
| 14 | |
| 15 | import numpy as np |
| 16 | from scipy import stats |
| 17 | |
| 18 | def calculate_sample_size(baseline_rate, mde, alpha=0.05, power=0.8): |
| 19 | """ |
| 20 | Calculate required sample size per variant. |
| 21 | baseline_rate: current conversion rate (e.g. 0.10) |
| 22 | mde: minimum detectable effect (relative, e.g. 0.05 = 5% lift) |
| 23 | """ |
| 24 | p1 = baseline_rate |
| 25 | p2 = baseline_rate * (1 + mde) |
| 26 | effect_size = abs(p2 - p1) / np.sqrt((p1 * (1 - p1) + p2 * (1 - p2)) / 2) |
| 27 | z_alpha = stats.norm.ppf(1 - alpha / 2) |
| 28 | z_beta = stats.norm.ppf(power) |
| 29 | n = ((z_alpha + z_beta) / effect_size) ** 2 |
| 30 | return int(np.ceil(n)) |
| 31 | |
| 32 | def analyze_experiment(control, treatment, alpha=0.05): |
| 33 | """ |
| 34 | Run two-proportion z-test and return structured results. |
| 35 | control/treatment: dicts with 'conversions' and 'visitors'. |
| 36 | """ |
| 37 | p_c = control["conversions"] / control["visitors"] |
| 38 | p_t = treatment["conversions"] / treatment["visitors"] |
| 39 | pooled = (control["conversions"] + treatment["conversions"]) / (control["visitors"] + treatment["visitors"]) |
| 40 | se = np.sqrt(pooled * (1 - pooled) * (1 / control["visitors"] + 1 / treatment["visitors"])) |
| 41 | z = (p_t - p_c) / se |
| 42 | p_value = 2 * (1 - stats.norm.cdf(abs(z))) |
| 43 | ci_low = (p_t - p_c) - stats.norm.ppf(1 - alpha / 2) * se |
| 44 | ci_high = (p_t - p_c) + stats.norm.ppf(1 - alpha / 2) * se |
| 45 | return { |
| 46 | "lift": (p_t - p_c) / p_c, |
| 47 | "p_value": p_value, |
| 48 | "significant": p_value < alpha, |
| 49 | "ci_95": (ci_low, ci_high), |
| 50 | } |
| 51 | |
| 52 | # --- Experiment checklist --- |
| 53 | # 1. Define ONE primary metric and pre-register secondary metrics. |
| 54 | # 2. Calculate sample size BEFORE starting: calculate_sample_size(0.10, 0.05) |
| 55 | # 3. Randomise at the user (not session) level to avoid leakage. |
| 56 | # 4. Run for at least 1 full business cycle (typically 2 weeks). |
| 57 | # 5. Check for sample ratio mismatch: abs(n_control - n_treatment) / expected < 0.01 |
| 58 | # 6. Analyze with analyze_experiment() and report lift + CI, not just p-value. |
| 59 | # 7. Apply Bonferroni correction if testing multiple metrics: alpha / n_metrics |
| 60 | |
| 61 | |
| 62 | ### 2. Build a Feature Engineering Pipeline |
| 63 | |
| 64 | |
| 65 | import pandas as pd |
| 66 | import numpy as np |
| 67 | from sklearn.pipeline import Pipeline |
| 68 | from sklearn.preprocessing import StandardScaler, OneHotEncoder |
| 69 | from sklearn.impute import SimpleImputer |
| 70 | from sklearn.compose import ColumnTransformer |
| 71 | |
| 72 | def build_feature_pipeline(numeric_cols, categorical_cols, date_cols=None): |
| 73 | """ |
| 74 | Returns a fitted-ready ColumnTransformer for structured tabular data. |
| 75 | """ |
| 76 | numeric_pipeline = Pipeline([ |
| 77 | ("impute", SimpleImputer(strategy="median")), |
| 78 | ("scale", StandardScaler()), |
| 79 | ]) |
| 80 | categorical_pipeline = Pipeline([ |
| 81 | ("impute", SimpleImputer(strategy="most_frequent")), |
| 82 | ("encode", OneHotEncoder(handle_unknown="ignore", sparse_output=False)), |
| 83 | ]) |
| 84 | transformers = [ |
| 85 | ("num", numeric_pipeline, numeric_cols), |
| 86 | ("cat", categorical_pipeline, categorical_cols), |
| 87 | ] |
| 88 | return ColumnTransformer(transformers, remainder="drop") |
| 89 | |
| 90 | def add_time_features(df, date_col): |
| 91 | """Extract cyclical and lag features from a datetime column.""" |
| 92 | df = df.copy() |
| 93 | df[date_col] = pd.to_datetime(df[date_col]) |
| 94 | df["dow_sin"] = np.sin(2 * np.pi * df[date_col].dt.dayofweek / 7) |
| 95 | df["dow_cos"] = np.cos(2 * np.pi * df[date_col].dt.dayofweek / 7) |
| 96 | df["month_sin"] = np.sin(2 * np.pi * df[date_col].dt.month / 12) |
| 97 | df["month_cos"] = np.cos(2 * np.pi * df[date_col].dt.month / 12) |
| 98 | df["is_weekend"] = (df[date_col].dt.dayofweek >= 5).astype(int) |
| 99 | return df |
| 100 | |
| 101 | # --- Feature engineering checklist --- |
| 102 | # 1. Never fit transformers on the full dataset — fit on train, transform test. |
| 103 | # 2. Log-transform right-skewed numeric features before scaling. |
| 104 | # 3. For high-cardinality categoricals (>50 levels), use target encoding or embeddings. |
| 105 | # 4. Generate lag/rolling features BEFORE the train/test split to avoid leakage. |
| 106 | # 5. Document each feature's business meaning alongside its code. |
| 107 | |
| 108 | |
| 109 | ### 3. Train, Evaluate, and Select a Prediction Model |
| 110 | |
| 111 | |
| 112 | from sklearn.model_selection import StratifiedKFold, cross_validate |
| 113 | from sklearn.metrics import make_scorer, roc_auc_score, average_precision_score |
| 114 | import xgboost as xgb |
| 115 | import mlflow |
| 116 | |
| 117 | SCORERS = { |
| 118 | "roc_auc": make_scorer(roc_auc_score, needs_proba=True), |
| 119 | "avg_prec": make_scorer(average_precision_score, needs_proba=True), |
| 120 | } |
| 121 | |
| 122 | def evaluate_model(model, X, y, cv=5): |
| 123 | """ |
| 124 | Cross-validate and return mean ± std for each scorer. |
| 125 | Use StratifiedKFold for classification to preserve class balance. |
| 126 | """ |
| 127 | cv_results = cross_validate( |
| 128 | model, X, y, |
| 129 | cv=StratifiedKFold(n_splits=cv, shuffle=True, random_state=42), |
| 130 | scoring=SCORERS, |
| 131 | return_train_score=True, |
| 132 | ) |
| 133 | summary = {} |
| 134 | for metric in SCORERS: |
| 135 | test_scores = cv_results[f"test_{metric}"] |
| 136 | summary[metric] = {"mean": test_scores.mean(), "std": test_scores.std()} |
| 137 | # Flag overfitting: large gap between train and test score |
| 138 | train_mean = cv_results[f"train_{metric}"].mean() |
| 139 | summary[metric]["overfit_gap"] = train_mean - test_scores.mean() |
| 140 | return summary |
| 141 | |
| 142 | def train_and_log(model, X_train, y_train, X_test, y_test, run_name): |
| 143 | """Train model and log all artefacts to MLflow.""" |
| 144 | with mlflow.start_run(run_name=run_name): |
| 145 | model.fit(X_train, y_train) |
| 146 | proba = model.predict_proba(X_test)[:, 1] |
| 147 | metrics = { |
| 148 | "roc_auc": roc_auc_score(y_test, proba), |
| 149 | "avg_prec": average_precision_score(y_test, proba), |
| 150 | } |
| 151 | mlflow.log_params(model.get_params()) |
| 152 | mlflow.log_metrics(metrics) |
| 153 | mlflow.sklearn.log_model(model, "model") |
| 154 | return metrics |
| 155 | |
| 156 | # --- Model evaluation checklist --- |
| 157 | # 1. Always report AUC-PR alongside AUC-ROC for imbalanced datasets. |
| 158 | # 2. Check overfit_gap > 0.05 as a warning sign of overfitting. |
| 159 | # 3. Calibrate probabilities (Platt scaling / isotonic) before production use. |
| 160 | # 4. Compute SHAP values to validate feature importance makes business sense. |
| 161 | # 5. Run a baseline (e.g. DummyClassifier) and verify the model beats it. |
| 162 | # 6. Log every run to MLflow — never rely on notebook output for comparison. |
| 163 | |
| 164 | |
| 165 | ### 4. Causal Inference: Difference-in-Differences |
| 166 | |
| 167 | |
| 168 | import statsmodels.formula.api as smf |
| 169 | |
| 170 | def diff_in_diff(df, outcome, treatment_col, post_col, controls=None): |
| 171 | """ |
| 172 | Estimate ATT via OLS DiD with optional covariates. |
| 173 | df must have: outcome, treatment_col (0/1), post_col (0/1). |
| 174 | Returns the interaction coefficient (treatment × post) and its p-value. |
| 175 | """ |
| 176 | covariates = " + ".join(controls) if controls else "" |
| 177 | formula = ( |
| 178 | f"{outcome} ~ {treatment_col} * {post_col}" |
| 179 | + (f" + {covariates}" if covariates else "") |
| 180 | ) |
| 181 | result = smf.ols(formula, data=df).fit(cov_type="HC3") |
| 182 | interaction = f"{treatment_col}:{post_col}" |
| 183 | return { |
| 184 | "att": result.params[interaction], |
| 185 | "p_value": result.pvalues[interaction], |
| 186 | "ci_95": result.conf_int().loc[interaction].tolist(), |
| 187 | "summary": result.summary(), |
| 188 | } |
| 189 | |
| 190 | # --- Causal inference checklist --- |
| 191 | # 1. Validate parallel trends in pre-period before trusting DiD estimates. |
| 192 | # 2. Use HC3 robust standard errors to handle heteroskedasticity. |
| 193 | # 3. For panel data, cluster SEs at the unit level (add groups= param to fit). |
| 194 | # 4. Consider propensity score matching if groups differ at baseline. |
| 195 | # 5. Report the ATT with confidence interval, not just statistical significance. |
| 196 | |
| 197 | |
| 198 | ## Reference Documentation |
| 199 | |
| 200 | **Statistical Methods:** `references/statistical_methods_advanced.md` |
| 201 | **Experiment Design Frameworks:** `references/experiment_design_frameworks.md` |
| 202 | **Feature Engineering Patterns:** `references/feature_engineering_patterns.md` |
| 203 | |
| 204 | ## Common Commands |
| 205 | |
| 206 | |
| 207 | # Testing & linting |
| 208 | python -m pytest tests/ -v --cov=src/ |
| 209 | python -m black src/ && python -m pylint src/ |
| 210 | |
| 211 | # Bundled pipeline scaffolds (stdlib runners — extend the process() body with project logic) |
| 212 | python3 scripts/experiment_designer.py --input experiment_spec.json --output experiment_design.json |
| 213 | python3 scripts/feature_engineering_pipeline.py --input raw_features.json --output features.json |
| 214 | python3 scripts/model_evaluation_suite.py --input model_predictions.json --output evaluation.json |
| 215 | # Each prints a JSON run report ({status, processed_items, start/end_time}); any status other |
| 216 | # than "completed" means the stage failed — fix before moving to the next pipeline stage. |
| 217 | |
| 218 |
Discussion
Aeon Time Series Machine LearningThis skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection, segmentation, and similarity search. Use when working with temporal data, sequential patterns, or time-indexed observations requiring specialized algorithms beyond standard ML approaches. Particularly suited for univariate and multivariate time series analysis with scikit-learn compatible APIs.deepTools: NGS Data Analysis ToolkitNGS analysis toolkit. BAM to bigWig conversion, QC (correlation, PCA, fingerprints), heatmaps/profiles (TSS, peaks), for ChIP-seq, RNA-seq, ATAC-seq visualization.Exploratory data analysisPerform bounded, local exploratory analysis of explicitly supported scientific files. Use for redacted CSV/TSV/JSON profiles; optional NumPy, HDF5, FASTA/FASTQ, and basic image metadata inspection; missingness/leakage audits; outlier and transformation sensitivity; and rigorous EDA report scaffolds. Other domain formats are reference-only and unknown formats fail closed.Neuropixels Data AnalysisAnalyze Neuropixels extracellular recordings end-to-end with SpikeInterface. Covers loading SpikeGLX/Open Ephys/NWB data, preprocessing, drift/motion correction, Kilosort4 (and CPU) spike sorting, quality metrics, and unit curation (threshold-based, model-based UnitRefine, and AI-assisted visual review). Use when working with Neuropixels 1.0/2.0 recordings, spike sorting, or extracellular electrophysiology analysis.
Browse more free Claude skills or everything in Data & analytics.