mcpbeat Sign in

Predictive Analytics Construction Agent Skill

Forecast project outcomes using historical data: cost overruns, schedule delays, risk probabilities. Machine learning models for construction prediction.

4k tokens
context cost
the whole folder, loaded on every use
3
files
instructions only
0
copies elsewhere
how many repositories repackaged it
264
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill predictive-analytics-construction

The instruction itself

7 sections, as written by the author

Predictive Analytics for Construction

Overview

Use historical project data to predict future outcomes: cost overruns, schedule delays, quality issues, and risks. Apply machine learning models tailored for construction industry patterns.

Business Case

Predictive analytics enables proactive project management:

  • Early Warning: Identify projects likely to overrun before it happens
  • Resource Optimization: Allocate resources based on predicted needs
  • Risk Mitigation: Focus on high-risk areas early
  • Better Estimates: Learn from historical accuracy

Technical Implementation

from dataclasses import dataclass, field
from typing import List, Dict, Any, Optional, Tuple
import pandas as pd
import numpy as np
from datetime import datetime
from sklearn.ensemble import RandomForestRegressor, GradientBoostingClassifier
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import mean_absolute_error, accuracy_score, classification_report
import warnings
warnings.filterwarnings('ignore')

@dataclass
class PredictionResult:
    prediction: float
    confidence: float
    prediction_type: str
    features_used: List[str]
    feature_importance: Dict[str, float]
    comparable_projects: List[str]
    risk_factors: List[str]

@dataclass
class ModelMetrics:
    model_name: str
    accuracy: float
    mae: float
    feature_importance: Dict[str, float]
    training_samples: int
    last_trained: datetime

class ConstructionPredictiveAnalytics:
    """Predictive analytics for construction projects."""

    def __init__(self):
        self.models: Dict[str, Any] = {}
        self.scalers: Dict[str, StandardScaler] = {}
        self.encoders: Dict[str, LabelEncoder] = {}
        self.metrics: Dict[str, ModelMetrics] = {}
        self.feature_columns: Dict[str, List[str]] = {}

    def prepare_features(self, df: pd.DataFrame, target_col: str) -> Tuple[pd.DataFrame, pd.Series]:
        """Prepare features for model training."""
        # Separate numeric and categorical columns
        numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
        categorical_cols = df.select_dtypes(include=['object', 'category']).columns.tolist()

        # Remove target from features
        if target_col in numeric_cols:
            numeric_cols.remove(target_col)
        if target_col in categorical_cols:
            categorical_cols.remove(target_col)

        # Encode categorical variables
        df_encoded = df.copy()
        for col in categorical_cols:
            if col not in self.encoders:
                self.encoders[col] = LabelEncoder()
                df_encoded[col] = self.encoders[col].fit_transform(df[col].astype(str))
            else:
                df_encoded[col] = self.encoders[col].transform(df[col].astype(str))

        feature_cols = numeric_cols + categorical_cols
        X = df_encoded[feature_cols].fillna(0)
        y = df[target_col]

        return X, y, feature_cols

    def train_cost_overrun_model(self, historical_data: pd.DataFrame) -> ModelMetrics:
        """Train model to predict cost overrun percentage."""
        # Expected columns: project_type, original_estimate, gross_area, duration_months,
        # num_change_orders, complexity_score, contractor_experience, final_cost

        required_cols = ['original_estimate', 'final_cost']
        if not all(col in historical_data.columns for col in required_cols):
            raise ValueError(f"Missing required columns: {required_cols}")

        # Calculate overrun percentage
        df = historical_data.copy()
        df['overrun_pct'] = ((df['final_cost'] - df['original_estimate']) / df['original_estimate']) * 100

        # Prepare features
        feature_cols = [col for col in df.columns if col not in ['final_cost', 'overrun_pct', 'project_id', 'project_name']]
        X, y, used_features = self.prepare_features(df[feature_cols + ['overrun_pct']], 'overrun_pct')

        # Split data
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

        # Scale features
        scaler = StandardScaler()
        X_train_scaled = scaler.fit_transform(X_train)
        X_test_scaled = scaler.transform(X_test)

        # Train model
        model = GradientBoostingRegressor(n_estimators=100, max_depth=5, random_state=42)
        model.fit(X_train_scaled, y_train)

        # Evaluate
        y_pred = model.predict(X_test_scaled)
        mae = mean_absolute_error(y_test, y_pred)

        # Cross-validation
        cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5, scoring='neg_mean_absolute_error')

        # Feature importance
        importance = dict(zip(used_features, model.feature_importances_))

        # Store model
        self.models['cost_overrun'] = model
        self.scalers['cost_overrun'] = scaler
        self.feature_columns['cost_overrun'] = used_features

        metrics = ModelMetrics(
            model_name='cost_overrun',
            accuracy=1 - (mae / df['overrun_pct'].std()),
            mae=mae,
            feature_importance=importance,
            training_samples=len(X_train),
            last_trained=datetime.now()
        )
        self.metrics['cost_overrun'] = metrics

        return metrics

    def train_schedule_delay_model(self, historical_data: pd.DataFrame) -> ModelMetrics:
        """Train model to predict schedule delay probability."""
        df = historical_data.copy()

        # Binary classification: was project delayed?
        df['was_delayed'] = (df['actual_duration'] > df['planned_duration']).astype(int)

        feature_cols = [col for col in df.columns
                       if col not in ['actual_duration', 'was_delayed', 'project_id', 'project_name']]

        X, y, used_features = self.prepare_features(df[feature_cols + ['was_delayed']], 'was_delayed')

        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

        scaler = StandardScaler()
        X_train_scaled = scaler.fit_transform(X_train)
        X_test_scaled = scaler.transform(X_test)

        model = GradientBoostingClassifier(n_estimators=100, max_depth=5, random_state=42)
        model.fit(X_train_scaled, y_train)

        y_pred = model.predict(X_test_scaled)
        accuracy = accuracy_score(y_test, y_pred)

        importance = dict(zip(used_features, model.feature_importances_))

        self.models['schedule_delay'] = model
        self.scalers['schedule_delay'] = scaler
        self.feature_columns['schedule_delay'] = used_features

        metrics = ModelMetrics(
            model_name='schedule_delay',
            accuracy=accuracy,
            mae=0,
            feature_importance=importance,
            training_samples=len(X_train),
            last_trained=datetime.now()
        )
        self.metrics['schedule_delay'] = metrics

        return metrics

    def predict_cost_overrun(self, project_data: Dict) -> PredictionResult:
        """Predict cost overrun for a new project."""
        if 'cost_overrun' not in self.models:
            raise ValueError("Cost overrun model not trained. Call train_cost_overrun_model first.")

        model = self.models['cost_overrun']
        scaler = self.scalers['cost_overrun']
        features = self.feature_columns['cost_overrun']

        # Prepare input
        input_df = pd.DataFrame([project_data])

        # Encode categorical
        for col in input_df.select_dtypes(include=['object']).columns:
            if col in self.encoders:
                input_df[col] = self.encoders[col].transform(input_df[col].astype(str))

        # Ensure all features present
        for feat in features:
            if feat not in input_df.columns:
                input_df[feat] = 0

        X = input_df[features].fillna(0)
        X_scaled = scaler.transform(X)

        prediction = model.predict(X_scaled)[0]

        # Get feature importance for this prediction
        importance = dict(zip(features, model.feature_importances_))
        top_features = sorted(importance.items(), key=lambda x: -x[1])[:5]

        # Identify risk factors
        risk_factors = []
        if prediction > 10:
            risk_factors.append(f"High overrun risk: {prediction:.1f}%")
        for feat, imp in top_features[:3]:
            risk_factors.append(f"Key factor: {feat} (importance: {imp:.2%})")

        return PredictionResult(
            prediction=prediction,
            confidence=0.8,  # Could calculate from model uncertainty
            prediction_type='cost_overrun_percentage',
            features_used=features,
            feature_importance=dict(top_features),
            comparable_projects=[],
            risk_factors=risk_factors
        )

    def predict_delay_probability(self, project_data: Dict) -> PredictionResult:
        """Predict probability of schedule delay."""
        if 'schedule_delay' not in self.models:
            raise ValueError("Schedule delay model not trained.")

        model = self.models['schedule_delay']
        scaler = self.scalers['schedule_delay']
        features = self.feature_columns['schedule_delay']

        input_df = pd.DataFrame([project_data])

        for col in input_df.select_dtypes(include=['object']).columns:
            if col in self.encoders:
                input_df[col] = self.encoders[col].transform(input_df[col].astype(str))

        for feat in features:
            if feat not in input_df.columns:
                input_df[feat] = 0

        X = input_df[features].fillna(0)
        X_scaled = scaler.transform(X)

        probability = model.predict_proba(X_scaled)[0][1]
        prediction = model.predict(X_scaled)[0]

        importance = dict(zip(features, model.feature_importances_))
        top_features = sorted(importance.items(), key=lambda x: -x[1])[:5]

        risk_factors = []
        if probability > 0.7:
            risk_factors.append(f"High delay probability: {probability:.1%}")
        elif probability > 0.4:
            risk_factors.append(f"Moderate delay probability: {probability:.1%}")

        return PredictionResult(
            prediction=probability,
            confidence=probability if prediction == 1 else 1 - probability,
            prediction_type='delay_probability',
            features_used=features,
            feature_importance=dict(top_features),
            comparable_projects=[],
            risk_factors=risk_factors
        )

    def find_similar_projects(self, project_data: Dict, historical_data: pd.DataFrame,
                             n: int = 5) -> pd.DataFrame:
        """Find similar projects from historical data."""
        from sklearn.neighbors import NearestNeighbors

        numeric_cols = historical_data.select_dtypes(include=[np.number]).columns.tolist()
        exclude = ['final_cost', 'actual_duration', 'overrun_pct']
        feature_cols = [c for c in numeric_cols if c not in exclude]

        X = historical_data[feature_cols].fillna(0)

        scaler = StandardScaler()
        X_scaled = scaler.fit_transform(X)

        # Prepare new project
        new_project = pd.DataFrame([project_data])[feature_cols].fillna(0)
        new_scaled = scaler.transform(new_project)

        # Find neighbors
        nn = NearestNeighbors(n_neighbors=min(n, len(X)), metric='euclidean')
        nn.fit(X_scaled)
        distances, indices = nn.kneighbors(new_scaled)

        similar = historical_data.iloc[indices[0]].copy()
        similar['similarity_score'] = 1 / (1 + distances[0])

        return similar

    def generate_prediction_report(self, project_data: Dict, historical_data: pd.DataFrame) -> str:
        """Generate comprehensive prediction report."""
        lines = ["# Project Prediction Report", ""]
        lines.append(f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}")
        lines.append(f"**Project:** {project_data.get('project_name', 'New Project')}")
        lines.append("")

        # Cost prediction
        if 'cost_overrun' in self.models:
            cost_pred = self.predict_cost_overrun(project_data)
            lines.append("## Cost Overrun Prediction")
            lines.append(f"**Predicted Overrun:** {cost_pred.prediction:.1f}%")
            lines.append(f"**Confidence:** {cost_pred.confidence:.1%}")
            lines.append("")
            lines.append("**Key Factors:**")
            for feat, imp in list(cost_pred.feature_importance.items())[:5]:
                lines.append(f"- {feat}: {imp:.2%}")
            lines.append("")

        # Schedule prediction
        if 'schedule_delay' in self.models:
            delay_pred = self.predict_delay_probability(project_data)
            lines.append("## Schedule Delay Prediction")
            lines.append(f"**Delay Probability:** {delay_pred.prediction:.1%}")
            lines.append("")

        # Similar projects
        lines.append("## Similar Historical Projects")
        similar = self.find_similar_projects(project_data, historical_data, n=5)
        for _, row in similar.iterrows():
            name = row.get('project_name', 'Project')
            overrun = row.get('overrun_pct', 0)
            similarity = row.get('similarity_score', 0)
            lines.append(f"- **{name}**: {overrun:.1f}% overrun (similarity: {similarity:.1%})")

        # Risk summary
        lines.append("")
        lines.append("## Risk Summary")
        all_risks = []
        if 'cost_overrun' in self.models:
            all_risks.extend(cost_pred.risk_factors)
        if 'schedule_delay' in self.models:
            all_risks.extend(delay_pred.risk_factors)

        for risk in all_risks:
            lines.append(f"- ⚠️ {risk}")

        return "\n".join(lines)

Quick Start

import pandas as pd

# Load historical data
historical = pd.read_excel("historical_projects.xlsx")

# Initialize analytics
analytics = ConstructionPredictiveAnalytics()

# Train models
cost_metrics = analytics.train_cost_overrun_model(historical)
print(f"Cost model MAE: {cost_metrics.mae:.2f}%")

delay_metrics = analytics.train_schedule_delay_model(historical)
print(f"Delay model accuracy: {delay_metrics.accuracy:.1%}")

# Predict for new project
new_project = {
    'project_type': 'Office',
    'original_estimate': 5000000,
    'gross_area': 50000,
    'duration_months': 18,
    'complexity_score': 7,
    'contractor_experience': 15
}

cost_prediction = analytics.predict_cost_overrun(new_project)
print(f"Predicted overrun: {cost_prediction.prediction:.1f}%")

delay_prediction = analytics.predict_delay_probability(new_project)
print(f"Delay probability: {delay_prediction.prediction:.1%}")

# Generate report
report = analytics.generate_prediction_report(new_project, historical)
print(report)

Dependencies

pip install pandas numpy scikit-learn

Resources

  • ML for Construction: Research on predictive models
  • Feature Engineering: Construction-specific features

Other skills for the same job

different authors, same section of the catalogue
XLSX
by anthropics
vendor ×15

Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas

5k tokens scripts
XLSX
by w95
×7

Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like \"the xlsx in my downloads\") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.

3k tokens
Raffle Winner Picker
by frostant
×5

Picks random winners from lists, spreadsheets, or Google Sheets for giveaways, raffles, and contests. Ensures fair, unbiased selection with transparency.

949 tokens
Fda Database
by christophacham
×4

Query openFDA API for drugs, devices, adverse events, recalls, regulatory submissions (510k, PMA), substance identification (UNII), for FDA regulatory data analysis and safety research.

32k tokens scripts
Matlab
by christophacham
×4

MATLAB and GNU Octave numerical computing for matrix operations, data analysis, visualization, and scientific computing. Use when writing MATLAB/Octave scripts for linear algebra, signal processing, image processing, differential equations, optimization, statistics, or creating scientific visualizations. Also use when the user needs help with MATLAB syntax, functions, or wants to convert between MATLAB and Python code. Scripts can be executed with MATLAB or the open-source GNU Octave interpreter.

25k tokens
Umap Learn
by ComeOnOliver
×4

UMAP dimensionality reduction. Fast nonlinear manifold learning for 2D/3D visualization, clustering preprocessing (HDBSCAN), supervised/parametric UMAP, for high-dimensional data.

14k tokens
D3 Viz
by chrisvoncsefalvay
×3

Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisations, or any complex SVG-based data visualisation that requires fine-grained control over visual elements, transitions, or interactions. Use this for bespoke visualisations beyond standard charting libraries, whether in React, Vue, Svelte, vanilla JavaScript, or any other environment.

20k tokens
Alphafold Database
by christophacham
×3

Access AlphaFold 200M+ AI-predicted protein structures. Retrieve structures by UniProt ID, download PDB/mmCIF files, analyze confidence metrics (pLDDT, PAE), for drug discovery and structural biology.

7k tokens

How to use it

Copy the folder

Take datadrivenconstruction/predictive-analytics-construction from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.

Install what it needs

The instructions reference pip. Without those the skill loads but fails at the first command.