Data Science Lesson 20 – Domain Features | Dataplexa
Feature Engineering · Lesson 20

Domain Features

Transform raw business data into powerful predictive features using industry expertise and domain knowledge from real e-commerce operations.

Domain features separate good data scientists from great ones. Raw data tells you what happened — domain features tell you why and predict what happens next. The difference? A 15% accuracy boost that comes from understanding your business, not just your algorithms.

Think about it this way. Your order_date column contains dates. But an e-commerce expert sees festive seasons, pay-day patterns, and weekend shopping behaviors. That business knowledge becomes features that predict customer behavior with scary accuracy.

Temporal

Extract seasonal patterns, holidays, weekends

Behavioral

Purchase frequency, loyalty signals

Geographic

City-based preferences, regional trends

Business

Profit margins, inventory cycles

Time-Based Features

The scenario: Myntra's data team notices revenue spikes but can't predict when they'll happen. Their current model treats Tuesday in July the same as Tuesday during Diwali sales. Big mistake.
# Load ecommerce data for temporal analysis
import pandas as pd
import numpy as np

# Read the dataset
df = pd.read_csv('dataplexa_ecommerce.csv')

# Convert date column to datetime for feature extraction
df['date'] = pd.to_datetime(df['date'])

What just happened?

We converted the date column from string format to datetime objects. Now Python recognizes these as actual dates, not just text. Try this: Check df.dtypes to see the difference.

Now comes the magic. Each date contains multiple business insights:
# Extract multiple time features from single date column
# Each feature captures different shopping patterns

# Day of week (0=Monday, 6=Sunday)
df['day_of_week'] = df['date'].dt.dayofweek

# Weekend indicator - shopping behavior differs
df['is_weekend'] = df['day_of_week'].isin([5, 6]).astype(int)

# Month for seasonal trends
df['month'] = df['date'].dt.month

What just happened?

From one date column, we created three new features. day_of_week=3 means Thursday, is_weekend=0 means weekday, and month=1 means January. Try this: Group by is_weekend and compare average revenue.

But we're just getting started. Festival seasons in India drive massive sales spikes:
# Create festival season features for Indian market
# These periods show 300-500% revenue increases

def get_festival_season(date):
    month = date.month
    # Diwali season (Oct-Nov)
    if month in [10, 11]:
        return 'diwali'
    # Wedding season (Dec-Feb)
    elif month in [12, 1, 2]:
        return 'wedding'
    # Summer sale season (Mar-May)
    elif month in [3, 4, 5]:
        return 'summer'
    else:
        return 'regular'
# Apply festival season to dataset
df['festival_season'] = df['date'].apply(get_festival_season)

# Convert categorical to dummy variables for ML models
festival_dummies = pd.get_dummies(df['festival_season'], prefix='season')

# Display the new features
print(df[['date', 'festival_season']].head())

What just happened?

January dates got labeled as wedding season because Indian weddings peak in winter months. The get_dummies() function converts these categories into binary columns like season_wedding. Try this: Compare revenue across different festival seasons.

Weekend purchases average 35% higher than weekdays - perfect for targeted promotions

The chart reveals weekend shopping behavior clearly. Saturday and Sunday show significantly higher revenue per transaction, suggesting customers have more time to browse and buy higher-value items. This pattern helps schedule promotional campaigns and inventory management. Your ML model can now distinguish between a regular Tuesday sale and a weekend shopping spree. That context matters because weekend customers behave differently — they research more, buy higher-ticket items, and respond better to premium product recommendations.

Customer Behavior Features

The scenario: Flipkart wants to predict which customers will make repeat purchases within 30 days. Age and gender aren't enough — they need behavioral signals that reveal purchase intent.
# Create customer-level behavioral features
# Group by customer to calculate their historical patterns

customer_behavior = df.groupby('customer_age').agg({
    'order_id': 'count',    # Total orders per customer
    'revenue': ['sum', 'mean'],  # Total spent and avg order value
    'quantity': 'sum',      # Total items purchased
    'returned': 'mean'      # Return rate as percentage
}).round(2)

What just happened?

We calculated key behavioral metrics per customer age group. count shows total orders, sum shows total revenue, mean shows average order value and return rate. Try this: Sort by return rate to identify problematic age segments.

But individual customer features tell a better story:
# Create purchase frequency features
# Calculate days since last purchase for each customer

df_sorted = df.sort_values(['customer_age', 'date'])

# Days between consecutive purchases
df_sorted['days_since_last'] = df_sorted.groupby('customer_age')['date'].diff().dt.days

# Fill first purchase with 0
df_sorted['days_since_last'] = df_sorted['days_since_last'].fillna(0)
# Create loyalty and value segmentation features
# Categorize customers based on behavior patterns

def create_customer_segment(row):
    avg_order = row['revenue']
    frequency = row['quantity']
    
    # High-value frequent buyers
    if avg_order > 50000 and frequency > 5:
        return 'premium'
    # Regular customers
    elif avg_order > 20000 and frequency > 2:
        return 'regular'
    # Price-sensitive buyers
    else:
        return 'budget'
# Apply customer segmentation to dataset
df['customer_segment'] = df.apply(create_customer_segment, axis=1)

# Show segment distribution
segment_counts = df['customer_segment'].value_counts()
print("Customer Segments:")
print(segment_counts)

What just happened?

We segmented customers into three behavioral categories based on their spending and purchase frequency. budget customers are price-sensitive, regular customers are steady buyers, and premium customers are high-value. Try this: Calculate average return rates for each segment.

📊 Data Insight

50% of customers fall into the budget segment, but premium customers (13.5%) likely generate 60-70% of total revenue due to higher order values and frequency.

Product and Category Features

The scenario: Swiggy wants to predict which food categories will be popular during specific weather conditions and times of day. They need features that capture product relationships and seasonal demand patterns.
# Calculate product performance metrics
# These reveal which products drive business success

product_metrics = df.groupby('product_category').agg({
    'revenue': ['sum', 'mean', 'std'],  # Financial performance
    'rating': 'mean',                   # Customer satisfaction
    'returned': 'mean',                 # Quality indicator
    'quantity': 'sum'                   # Popularity measure
}).round(2)
# Create price positioning features
# Categorize products by price range for targeted marketing

def price_tier(revenue, quantity):
    unit_price = revenue / quantity if quantity > 0 else 0
    
    if unit_price > 15000:
        return 'premium'
    elif unit_price > 5000:
        return 'mid-range'
    else:
        return 'economy'

# Apply price tier classification
df['price_tier'] = df.apply(lambda x: price_tier(x['revenue'], x['quantity']), axis=1)
# Analyze price tier distribution and performance
price_analysis = df.groupby(['product_category', 'price_tier']).agg({
    'order_id': 'count',
    'revenue': 'mean',
    'rating': 'mean'
}).round(2)

print("Price Tier Performance by Category:")
print(price_analysis.head(8))

What just happened?

We created price tiers by calculating unit price and categorizing products. Electronics premium items average ₹28,450 per order with decent ratings (4.1), while economy electronics only average ₹2,156. Try this: Compare return rates across price tiers to spot quality issues.

Premium products drive 58% of revenue despite being only 25% of total orders

This distribution shows the classic 80/20 rule in action. Premium products generate the majority of revenue, which means your recommendation algorithms should prioritize showing premium items to customers who can afford them. The price tier becomes a crucial feature for customer segmentation. Your models can now predict not just what customers will buy, but which price range they prefer. This enables dynamic pricing strategies and personalized product recommendations that match both customer preferences and business profitability goals.

Geographic and Demographic Features

Cities in India show dramatically different shopping patterns. Mumbai customers prefer premium electronics, while Pune customers buy more books and home goods. Geography matters more than you think.
# Create city-based purchasing power indicators
# Different cities have different economic profiles

city_profiles = df.groupby('city').agg({
    'revenue': ['mean', 'std'],         # Average spending and variance
    'customer_age': 'mean',             # Demographics
    'rating': 'mean',                   # Satisfaction levels
    'returned': 'mean'                  # Return behavior
}).round(2)

print("City Purchasing Profiles:")
print(city_profiles)
# Create city tier classification
# Metro cities behave differently than smaller cities

def classify_city_tier(city_name, avg_revenue):
    # Tier 1 cities with highest purchasing power
    tier1_cities = ['Mumbai', 'Delhi', 'Bangalore']
    
    if city_name in tier1_cities and avg_revenue > 4000:
        return 'tier1_high'
    elif city_name in tier1_cities:
        return 'tier1_medium'
    else:
        return 'tier2'

# Apply city classification
city_data = city_profiles.reset_index()
city_data['city_tier'] = city_data.apply(
    lambda x: classify_city_tier(x['city'], x[('revenue', 'mean')]), axis=1
)
# Map city tiers back to original dataset
city_tier_map = dict(zip(city_data['city'], city_data['city_tier']))

df['city_tier'] = df['city'].map(city_tier_map)

# Show city tier distribution
tier_distribution = df['city_tier'].value_counts()
print("City Tier Distribution:")
print(tier_distribution)

What just happened?

We classified cities into tiers based on spending patterns. Mumbai, Delhi, and Bangalore with high average revenue became tier1_high, while Chennai and Pune became tier2 cities. Try this: Analyze which product categories perform best in each tier.

Mumbai customers consistently spend 20-40% more across all age groups compared to other cities

The geographic patterns are clear and actionable. Mumbai's premium spending behavior suggests your algorithms should show higher-value products to Mumbai customers first. The age curves also reveal that 36-45 year-olds are peak earners regardless of city. These domain features transform your models from generic predictors to business-smart systems. Instead of treating all customers the same, you can now personalize based on location, age, spending tier, and behavioral patterns — exactly what successful e-commerce platforms do.

📊 Data Insight

Combining geographic and behavioral features often improves model accuracy by 12-18% compared to using demographic features alone — the business context matters more than raw statistics.

Common Mistake: Feature Explosion

Don't create 50 domain features and hope for the best. Start with 5-8 features that directly relate to your business problem. More features often mean more noise, not more signal. Focus on features that capture genuine business insights, not clever mathematical transformations.

Validation and Impact

Domain features only matter if they improve predictions. Here's how to validate their business impact:
# Create feature importance comparison
# Test which domain features actually improve predictions

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

# Prepare features for modeling
feature_columns = ['customer_age', 'day_of_week', 'is_weekend', 
                   'month', 'days_since_last', 'quantity']

# Convert categorical features to numeric
le = LabelEncoder()
df['city_encoded'] = le.fit_transform(df['city'])
df['category_encoded'] = le.fit_transform(df['product_category'])

What just happened?

We converted categorical features like city names and product categories into numeric codes that machine learning algorithms can understand. LabelEncoder assigns each unique value a number. Try this: Use pd.get_dummies() instead for better categorical handling.

Domain expertise beats algorithmic cleverness every time. The features you create from understanding your customers, their behavior, and your market context will outperform any fancy mathematical transformation. Your job? Think like a business owner, then code like a data scientist.

Quiz

1. An e-commerce company wants to predict daily revenue spikes. Which domain features would be most valuable from their order date column?


2. Your dataset shows customers with ages 18-65 but age alone doesn't predict purchasing behavior well. What domain feature engineering approach would be most effective?


3. A data scientist creates 15 domain features that improve model accuracy by 12%. What is the main limitation they should consider?


Up Next

Descriptive Statistics

Master the fundamental statistical measures that reveal hidden patterns in your domain features and guide data-driven business decisions.