원클릭으로
pipeline-explore
Profile dataset structure, clean data quality issues, and produce exploration artifacts for downstream analysis
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Profile dataset structure, clean data quality issues, and produce exploration artifacts for downstream analysis
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Evaluate scientific hypotheses using appropriate statistical methods and predictive modeling while preserving standardized verdict outputs
Generate diverse, novel, falsifiable hypotheses across statistical, ML, biological, and data-quality dimensions — querying existing hypotheses first to maximize coverage
Query alzkb.ai Alzheimer's knowledge graph using Neo4j Cypher. Use when answering questions about Alzheimer's disease, genes, drugs, biological processes, pathways, symptoms, molecular functions, cellular components, body parts, or drug classes from the alzkb.ai knowledge base. Triggers on queries like "find genes associated with...", "what drugs treat...", "which biological processes involve...", "how is X related to Y", or "query the alzkb knowledge graph".
| name | pipeline-explore |
| description | Profile dataset structure, clean data quality issues, and produce exploration artifacts for downstream analysis |
| when | use when running the exploration phase on a normalized dataset |
| visibility | public |
| tags | ["pipeline","explore","cleaning","eda","profiling"] |
| author | system |
| version | 1.0.0 |
You are the exploration phase of a scientific analysis pipeline. Your job is to deeply understand the dataset, fix data quality issues, and produce clean artifacts that downstream hypothesis and testing agents can rely on. Do NOT perform that actual hypothesis generation and testing. You are only to explore and assume that subsequent analysis would use your EDA as reference. Once you create the exploration_report.md, terminate any further analysis.
| File | Description |
|---|---|
output/cleaned_data.feather | Cleaned, analysis-ready data table |
output/exploration_report.md | Findings, quality issues, column descriptions |
import pandas as pd
import numpy as np
import json
import os
import glob
dataset_id = os.environ.get('DATASET_ID', '')
domain = os.environ.get('DATASET_DOMAIN', 'unknown')
base = f'/datasets/{dataset_id}/normalized'
# Read semantic context first
with open(f'{base}/semantic.json') as f:
semantic = json.load(f)
entities = semantic.get('entities', [])
units = semantic.get('units', {})
# Discover all table feather files (table_1.feather, table_2.feather, ...)
import pyarrow.feather as feather
table_files = sorted(glob.glob(f'{base}/tables/table_*.feather'))
if not table_files:
raise FileNotFoundError(f"No table feather files found in {base}/tables/")
# Load all tables
tables = {os.path.basename(f).replace('.feather', ''): feather.read_table(f).to_pandas() for f in table_files}
df = tables[list(tables.keys())[0]] # primary table for cleaning/profiling
print(f"Found {len(tables)} table(s): {list(tables.keys())}")
print(f"Primary table: {df.shape[0]} rows × {df.shape[1]} columns")
# Basic statistics
profile = {
'shape': df.shape,
'dtypes': df.dtypes.astype(str).to_dict(),
'missing_counts': df.isnull().sum().to_dict(),
'missing_pct': (df.isnull().mean() * 100).round(2).to_dict(),
'duplicates': int(df.duplicated().sum()),
'numeric_stats': df.describe().to_dict()
}
# Identify columns by type
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
categorical_cols = df.select_dtypes(include=['object', 'category']).columns.tolist()
print(f"Numeric: {len(numeric_cols)}, Categorical: {len(categorical_cols)}")
print(f"Missing: {sum(profile['missing_counts'].values())} total cells")
print(f"Duplicates: {profile['duplicates']}")
df_clean = df.copy()
# Remove exact duplicates
df_clean.drop_duplicates(inplace=True)
# Impute missing — numeric: median, categorical: mode
for col in numeric_cols:
if df_clean[col].isnull().any():
median_val = df_clean[col].median()
df_clean[col].fillna(median_val, inplace=True)
for col in categorical_cols:
if df_clean[col].isnull().any():
mode_val = df_clean[col].mode()
fill = mode_val[0] if not mode_val.empty else 'Unknown'
df_clean[col].fillna(fill, inplace=True)
# Cap outliers using IQR (genomics/clinical data — preserve biological extremes cautiously)
for col in numeric_cols:
Q1, Q3 = df_clean[col].quantile(0.25), df_clean[col].quantile(0.75)
IQR = Q3 - Q1
lower, upper = Q1 - 3 * IQR, Q3 + 3 * IQR # 3×IQR for biological data
df_clean[col] = df_clean[col].clip(lower, upper)
print(f"After cleaning: {df_clean.shape[0]} rows (removed {len(df) - len(df_clean)} rows)")
# Try to infer the target column (last column, or named outcome/label/target/diagnosis)
target_candidates = [c for c in df_clean.columns
if any(kw in c.lower() for kw in ['target', 'label', 'outcome', 'diagnosis', 'class', 'y'])]
target_col = target_candidates[0] if target_candidates else df_clean.columns[-1]
print(f"Likely target column: {target_col}")
if df_clean[target_col].nunique() < 20:
print(f"Target distribution:\n{df_clean[target_col].value_counts()}")
import os
os.makedirs('/workspace/output', exist_ok=True)
# Save cleaned data
import pyarrow.feather as feather
feather.write_feather(df_clean, '/workspace/output/cleaned_data.feather')
# Write exploration report
report = f"""# Exploration Report
## Dataset Overview
- **Dataset ID:** {dataset_id}
- **Domain:** {domain}
- **Original shape:** {df.shape[0]} rows × {df.shape[1]} columns
- **After cleaning:** {df_clean.shape[0]} rows × {df_clean.shape[1]} columns
- **Entities identified:** {', '.join(entities) if entities else 'none'}
## Sheets / Tables
| Table | Rows | Columns |
|---|---|---|
"""
for tname, tdf in tables.items():
report += f"| {tname} | {tdf.shape[0]} | {tdf.shape[1]} |\n"
report += f"""
## Data Quality
| Issue | Count |
|---|---|
| Missing values (original) | {sum(profile['missing_counts'].values())} |
| Duplicate rows | {profile['duplicates']} |
### Missing Values by Column
"""
for col, pct in profile['missing_pct'].items():
if pct > 0:
report += f"- `{col}`: {pct}% missing\n"
report += f"""
## Column Summary
### Numeric Columns ({len(numeric_cols)})
"""
for col in numeric_cols:
stats = df_clean[col].describe()
report += f"- `{col}`: mean={stats['mean']:.3f}, std={stats['std']:.3f}, range=[{stats['min']:.3f}, {stats['max']:.3f}]\n"
report += f"""
### Categorical Columns ({len(categorical_cols)})
"""
for col in categorical_cols:
report += f"- `{col}`: {df_clean[col].nunique()} unique values\n"
report += f"""
## Inferred Target
- **Column:** `{target_col}`
- **Type:** {'categorical' if df_clean[target_col].nunique() < 20 else 'continuous'}
## Cleaning Operations Applied
- Removed duplicate rows
- Imputed missing numeric values with column median
- Imputed missing categorical values with column mode
- Capped extreme outliers at 3×IQR bounds
"""
with open('/workspace/output/exploration_report.md', 'w') as f:
f.write(report)
print("Saved: output/cleaned_data.feather, output/exploration_report.md")
print("SKILL_INVOKED: public:pipeline-explore")