Skip to main content

exploratory-data-analysis

Initial data investigation techniques to discover patterns, spot anomalies, test hypotheses, and check assumptions using summary statistics and visualization.

Source facts

Repository
ffsshhttiikk/opencode-agents-skills
Last source activity
February 28, 2026 at 22:49
Detected SKILL.md language
English
Stars
3
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
exploratory-data-analysis
description
Initial data investigation techniques to discover patterns, spot anomalies, test hypotheses, and check assumptions using summary statistics and visualization.
category
data-science
keywords
["exploratory-data-analysis","eda","data exploration","data profiling","hypothesis testing","pattern discovery","data understanding","initial analysis"]
difficulty
beginner
related_skills
["pandas","numpy","statistics","data-visualization"]
# Exploratory Data Analysis ## What I do I provide techniques for initial data investigation to understand its structure, identify patterns, detect anomalies, formulate hypotheses, and guide feature engineering. EDA is the foundational step in any data science project that informs subsequent analysis and modeling decisions through systematic exploration and visualization. ## When to use me - At the start of any data science project - Understanding data structure and quality - Identifying relationships between variables - Detecting outliers and anomalies - Formulating hypotheses for testing - Guiding feature engineering decisions - Communicating data characteristics to stakeholders - Validating data collection assumptions ## Core Concepts ### Data Profiling - **Structure discovery**: Dimensions, data types, memory usage - **Value distributions**: Histograms, density plots, frequency counts - **Missing value analysis**: Patterns of missingness - **Duplicate detection**: Exact and fuzzy duplicates ### Univariate Analysis - **Central tendency**: Mean, median, mode - **Dispersion**: Range, variance, std, IQR - **Shape**: Skewness, kurtosis, percentiles - **Outlier detection**: Z-scores, IQR method ### Bivariate/Multivariate Analysis - **Correlation**: Pearson, Spearman, Kendall - **Relationships**: Scatter plots, pair plots - **Group comparisons**: Box plots, violin plots - **Dimensionality reduction**: PCA for visualization ### Statistical Testing - **Normality tests**: Shapiro-Wilk, D'Agostino - **Outlier tests**: Grubbs, Dixon's Q - **Homogeneity tests**: Levene, Bartlett - **Independence tests**: Chi-square, Fisher's exact ## Code Examples (Python) ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from scipy import stats # Basic data overview df = pd.read_csv('data.csv') # Structure information print(f"Shape: {df.shape}") print(f"\nColumn types:\n{df.dtypes}") print(f"\nMemory usage: {df.memory_usage(deep=True).sum() / 1024**2:.2f} MB") # First and last rows print(df.head(10)) print(df.tail(5)) # Summary statistics - numerical numerical_cols = df.select_dtypes(include=[np.number]).columns numerical_summary = df[numerical_cols].describe(percentiles=[.01, .05, .25, .5, .75, .95, .99]) print(numerical_summary) # Summary statistics - categorical categorical_cols = df.select_dtypes(include=['object', 'category']).columns for col in categorical_cols: print(f"\n{col}:") print(f" Unique values: {df[col].nunique()}") print(f" Value counts:\n{df[col].value_counts().head(10)}") print(f" Missing: {df[col].isnull().sum()} ({df[col].isnull().mean()*100:.1f}%)") # Missing value analysis missing = df.isnull().sum() missing_pct = (df.isnull().sum() / len(df) * 100).round(2) missing_df = pd.DataFrame({'Missing': missing, 'Percent': missing_pct}) missing_df = missing_df[missing_df['Missing'] > 0].sort_values('Percent', ascending=False) print(f"\nMissing Values:\n{missing_df}") # Missing value patterns missing_pattern = df.isnull().sum(axis=1).value_counts().sort_index() print(f"\nMissing values per row:\n{missing_pattern}") # Duplicate analysis print(f"\nExact duplicates: {df.duplicated().sum()}") print(f"Duplicate rows:\n{df[df.duplicated(keep=False)].sort_values(list(df.columns))}") # Outlier detection def detect_outliers_iqr(series): Q1 = series.quantile(0.25) Q3 = series.quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR return (series < lower_bound) | (series > upper_bound), lower_bound, upper_bound for col in numerical_cols: outliers, lb, ub = detect_outliers_iqr(df[col].dropna()) n_outliers = outliers.sum() pct_outliers = n_outliers / len(df) * 100 print(f"{col}: {n_outliers} outliers ({pct_outliers:.1f}%), bounds: [{lb:.2f}, {ub:.2f}]") # Normality tests for col in numerical_cols: if df[col].notna().sum() > 20: stat, p_value = stats.shapiro(df[col].dropna().sample(min(5000, len(df[col])))) is_normal = 'Normal' if p_value > 0.05 else 'Non-normal' print(f"{col}: Shapiro-Wilk p={p_value:.4f} → {is_normal}") # Correlation analysis correlation_matrix = df[numerical_cols].corr() print(f"\nCorrelation matrix:\n{correlation_matrix}") # Top correlations corr_pairs = [] for i in range(len(correlation_matrix.columns)): for j in range(i+1, len(correlation_matrix.columns)): corr_pairs.append({ 'Variable 1': correlation_matrix.columns[i], 'Variable 2': correlation_matrix.columns[j], 'Correlation': correlation_matrix.iloc[i, j] }) corr_df = pd.DataFrame(corr_pairs).sort_values('Correlation', key=abs, ascending=False) print(f"\nTop 10 Correlations:\n{corr_df.head(10)}") # Distribution analysis fig, axes = plt.subplots(2, 4, figsize=(16, 8)) axes = axes.flatten() for i, col in enumerate(numerical_cols[:8]): ax = axes[i] df[col].hist(bins=50, ax=ax, alpha=0.7) ax.set_title(f'{col}\nSkew: {df[col].skew():.2f}') ax.axvline(df[col].mean(), color='red', linestyle='--', label='Mean') ax.axvline(df[col].median(), color='green', linestyle='-', label='Median') ax.legend(fontsize=8) plt.tight_layout() plt.savefig('distributions.png', dpi=150) plt.show() # Box plots by category fig, axes = plt.subplots(2, 3, figsize=(15, 10)) axes = axes.flatten() for i, col in enumerate(numerical_cols[:6]): if len(categorical_cols) > 0: sns.boxplot(x=categorical_cols[0], y=col, data=df, ax=axes[i]) axes[i].set_title(f'{col} by {categorical_cols[0] if len(categorical_cols) > 0 else "all"}') axes[i].tick_params(axis='x', rotation=45) plt.tight_layout() plt.savefig('boxplots.png', dpi=150) plt.show() # Scatter plots for highly correlated variables fig, axes = plt.subplots(2, 3, figsize=(15, 10)) axes = axes.flatten() for i, row in corr_df.head(6).iterrows(): ax = axes[i] x, y = row['Variable 1'], row['Variable 2'] df_sample = df[[x, y]].dropna().sample(min(1000, len(df))) ax.scatter(df_sample[x], df_sample[y], alpha=0.3) ax.set_xlabel(x) ax.set_ylabel(y) ax.set_title(f'{x} vs {y}\nCorr: {row["Correlation"]:.3f}') plt.tight_layout() plt.savefig('scatterplots.png', dpi=150) plt.show() # Heatmap plt.figure(figsize=(12, 10)) sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0, fmt='.2f', square=True, linewidths=0.5) plt.title('Correlation Heatmap') plt.tight_layout() plt.savefig('correlation_heatmap.png', dpi=150) plt.show() # Pair plot for selected variables selected_cols = numerical_cols[:4].tolist() if len(categorical_cols) > 0: selected_cols.append(categorical_cols[0]) sns.pairplot(df[selected_cols].dropna(), hue=categorical_cols[0] if len(categorical_cols) > 0 else None, diag_kind='kde', plot_kws={'alpha': 0.5}) plt.savefig('pairplot.png', dpi=150) plt.show() # Categorical analysis fig, axes = plt.subplots(1, len(categorical_cols[:4]), figsize=(15, 4)) for i, col in enumerate(categorical_cols[:4]): value_counts = df[col].value_counts().head(10) axes[i].barh(value_counts.index, value_counts.values) axes[i].set_xlabel('Count') axes[i].set_title(f'{col}') axes[i].invert_yaxis() plt.tight_layout() plt.savefig('categorical_counts.png', dpi=150) plt.show() # Cross-tabulation if len(categorical_cols) >= 2: ct = pd.crosstab(df[categorical_cols[0]], df[categorical_cols[1]], margins=True, normalize='index') print(f"\nCross-tabulation:\n{ct}") # Time-based analysis if date column exists date_cols = [col for col in df.columns if 'date' in col.lower() or 'time' in col.lower()] if date_cols: df[date_cols[0]] = pd.to_datetime(df[date_cols[0]], errors='coerce') df['year'] = df[date_cols[0]].dt.year df['month'] = df[date_cols[0]].dt.month df['day_of_week'] = df[date_cols[0]].dt.dayofweek temporal_summary = df.groupby(['year', 'month'])[numerical_cols[0]].agg(['count', 'mean', 'std']) print(f"\nTemporal summary:\n{temporal_summary}") # Cardinality analysis cardinality = df[categorical_cols].nunique() print(f"\nCardinality:\n{cardinality}") # Unique value analysis for col in categorical_cols: print(f"\n{col} unique values: {df[col].nunique()}") if df[col].nunique() < 20: print(df[col].value_counts()) # Chi-square test for categorical independence if len(categorical_cols) >= 2: contingency = pd.crosstab(df[categorical_cols[0]], df[categorical_cols[1]]) chi2, p, dof, expected = stats.chi2_contingency(contingency) print(f"\nChi-square test ({categorical_cols[0]} vs {categorical_cols[1]}):") print(f" Chi2: {chi2:.4f}, p-value: {p:.4f}, dof: {dof}") ``` ## Best Practices 1. **Start simple**: Begin with basic structure and summary statistics before complex analysis. 2. **Visualize distributions**: Always plot your data; summary statistics can be misleading. 3. **Check for anomalies**: Look for impossible values, duplicates, and unexpected patterns. 4. **Understand missingness**: Is missingness random, or does it carry information? 5. **Iterative exploration**: Let findings guide further investigation; don't pre-plan everything. 6. **Document everything**: Keep track of what you find and what questions remain. 7. **Sample wisely**: For large datasets, sample intelligently for visualization. 8. **Consider context**: Domain knowledge should guide and validate your exploration. ## Common Patterns ### Pattern 1: Automated EDA Report Generator ```python def generate_eda_report(df, output_dir='.'): """Generate comprehensive EDA report.""" report = {} # Basic info report['shape'] = df.shape report['dtypes'] = df.dtypes.to_dict() report['missing'] = df.isnull().sum().to_dict() report['duplicates'] = df.duplicated().sum() # Numerical summary numerical = df.select_dtypes(include=[np.number])
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub