$npx -y skills add anthropics/knowledge-work-plugins --skill statistical-analysisstatistical-analysis is an agent skill published from anthropics/knowledge-work-plugins, installable through the skills CLI.
| 1 | # Statistical Analysis Skill |
| 2 | |
| 3 | Descriptive statistics, trend analysis, outlier detection, hypothesis testing, and guidance on when to be cautious about statistical claims. |
| 4 | |
| 5 | ## Descriptive Statistics Methodology |
| 6 | |
| 7 | ### Central Tendency |
| 8 | |
| 9 | Choose the right measure of center based on the data: |
| 10 | |
| 11 | | Situation | Use | Why | |
| 12 | |---|---|---| |
| 13 | | Symmetric distribution, no outliers | Mean | Most efficient estimator | |
| 14 | | Skewed distribution | Median | Robust to outliers | |
| 15 | | Categorical or ordinal data | Mode | Only option for non-numeric | |
| 16 | | Highly skewed with outliers (e.g., revenue per user) | Median + mean | Report both; the gap shows skew | |
| 17 | |
| 18 | **Always report mean and median together for business metrics.** If they diverge significantly, the data is skewed and the mean alone is misleading. |
| 19 | |
| 20 | ### Spread and Variability |
| 21 | |
| 22 | - **Standard deviation**: How far values typically fall from the mean. Use with normally distributed data. |
| 23 | - **Interquartile range (IQR)**: Distance from p25 to p75. Robust to outliers. Use with skewed data. |
| 24 | - **Coefficient of variation (CV)**: StdDev / Mean. Use to compare variability across metrics with different scales. |
| 25 | - **Range**: Max minus min. Sensitive to outliers but gives a quick sense of data extent. |
| 26 | |
| 27 | ### Percentiles for Business Context |
| 28 | |
| 29 | Report key percentiles to tell a richer story than mean alone: |
| 30 | |
| 31 | ``` |
| 32 | p1: Bottom 1% (floor / minimum typical value) |
| 33 | p5: Low end of normal range |
| 34 | p25: First quartile |
| 35 | p50: Median (typical user) |
| 36 | p75: Third quartile |
| 37 | p90: Top 10% / power users |
| 38 | p95: High end of normal range |
| 39 | p99: Top 1% / extreme users |
| 40 | ``` |
| 41 | |
| 42 | **Example narrative**: "The median session duration is 4.2 minutes, but the top 10% of users spend over 22 minutes per session, pulling the mean up to 7.8 minutes." |
| 43 | |
| 44 | ### Describing Distributions |
| 45 | |
| 46 | Characterize every numeric distribution you analyze: |
| 47 | |
| 48 | - **Shape**: Normal, right-skewed, left-skewed, bimodal, uniform, heavy-tailed |
| 49 | - **Center**: Mean and median (and the gap between them) |
| 50 | - **Spread**: Standard deviation or IQR |
| 51 | - **Outliers**: How many and how extreme |
| 52 | - **Bounds**: Is there a natural floor (zero) or ceiling (100%)? |
| 53 | |
| 54 | ## Trend Analysis and Forecasting |
| 55 | |
| 56 | ### Identifying Trends |
| 57 | |
| 58 | **Moving averages** to smooth noise: |
| 59 | ```python |
| 60 | # 7-day moving average (good for daily data with weekly seasonality) |
| 61 | df['ma_7d'] = df['metric'].rolling(window=7, min_periods=1).mean() |
| 62 | |
| 63 | # 28-day moving average (smooths weekly AND monthly patterns) |
| 64 | df['ma_28d'] = df['metric'].rolling(window=28, min_periods=1).mean() |
| 65 | ``` |
| 66 | |
| 67 | **Period-over-period comparison**: |
| 68 | - Week-over-week (WoW): Compare to same day last week |
| 69 | - Month-over-month (MoM): Compare to same month prior |
| 70 | - Year-over-year (YoY): Gold standard for seasonal businesses |
| 71 | - Same-day-last-year: Compare specific calendar day |
| 72 | |
| 73 | **Growth rates**: |
| 74 | ``` |
| 75 | Simple growth: (current - previous) / previous |
| 76 | CAGR: (ending / beginning) ^ (1 / years) - 1 |
| 77 | Log growth: ln(current / previous) -- better for volatile series |
| 78 | ``` |
| 79 | |
| 80 | ### Seasonality Detection |
| 81 | |
| 82 | Check for periodic patterns: |
| 83 | 1. Plot the raw time series -- visual inspection first |
| 84 | 2. Compute day-of-week averages: is there a clear weekly pattern? |
| 85 | 3. Compute month-of-year averages: is there an annual cycle? |
| 86 | 4. When comparing periods, always use YoY or same-period comparisons to avoid conflating trend with seasonality |
| 87 | |
| 88 | ### Forecasting (Simple Methods) |
| 89 | |
| 90 | For business analysts (not data scientists), use straightforward methods: |
| 91 | |
| 92 | - **Naive forecast**: Tomorrow = today. Use as a baseline. |
| 93 | - **Seasonal naive**: Tomorrow = same day last week/year. |
| 94 | - **Linear trend**: Fit a line to historical data. Only for clearly linear trends. |
| 95 | - **Moving average forecast**: Use trailing average as the forecast. |
| 96 | |
| 97 | **Always communicate uncertainty**. Provide a range, not a point estimate: |
| 98 | - "We expect 10K-12K signups next month based on the 3-month trend" |
| 99 | - NOT "We will get exactly 11,234 signups next month" |
| 100 | |
| 101 | **When to escalate to a data scientist**: Non-linear trends, multiple seasonalities, external factors (marketing spend, holidays), or when forecast accuracy matters for resource allocation. |
| 102 | |
| 103 | ## Outlier and Anomaly Detection |
| 104 | |
| 105 | ### Statistical Methods |
| 106 | |
| 107 | **Z-score method** (for normally distributed data): |
| 108 | ```python |
| 109 | z_scores = (df['value'] - df['value'].mean()) / df['value'].std() |
| 110 | outliers = df[abs(z_scores) > 3] # More than 3 standard deviations |
| 111 | ``` |
| 112 | |
| 113 | **IQR method** (robust to non-normal distributions): |
| 114 | ```python |
| 115 | Q1 = df['value'].quantile(0.25) |
| 116 | Q3 = df['value'].quantile(0.75) |
| 117 | IQR = Q3 - Q1 |
| 118 | lower_bound = Q1 - 1.5 * IQR |
| 119 | upper_bound = Q3 + 1.5 * IQR |
| 120 | outliers = df[(df['value'] < lower_bound) | (df['value'] > upper_bound)] |
| 121 | ``` |
| 122 | |
| 123 | **Percentile method** (simplest): |
| 124 | ```python |
| 125 | outliers = df[(df['value'] < df['value'].qua |