-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdata_feature_engineering.py
More file actions
96 lines (80 loc) · 3.59 KB
/
Copy pathdata_feature_engineering.py
File metadata and controls
96 lines (80 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# ================================================================
# 3. Feature Engineering Module
# Extracting time-based and derived features from timestamps
# ================================================================
import pandas as pd
# ----------------------------------------------------------------
# Helper function to classify hour into time period
# ----------------------------------------------------------------
def get_time_period(hour):
"""
Converts an hour (int) into a part of day:
Morning, Afternoon, Evening, or Night.
"""
if pd.isna(hour):
return None
if 5 <= hour < 12:
return 'Morning'
elif 12 <= hour < 17:
return 'Afternoon'
elif 17 <= hour < 21:
return 'Evening'
else:
return 'Night'
# ----------------------------------------------------------------
# Main feature engineering function
# ----------------------------------------------------------------
def engineer_features(df):
"""
Adds new features to the dataframe:
- Request hour, Request day (weekday)
- Time slot (Morning, Evening...)
- Trip duration (text + numeric in minutes)
- Driver availability, Trip completion, Request date
"""
print("🧠 Feature engineering...")
# Extract hour and day from the request timestamp
df = df[df['Request timestamp'].notna()]
df['Request hour'] = df['Request timestamp'].dt.hour
df['Request day'] = df['Request timestamp'].dt.dayofweek
df['Request hour'] = df['Request hour'].astype('Int64')
df['Request day'] = df['Request day'].astype('Int64')
# Map numeric day to weekday name
weekday_map = {
0: 'Monday', 1: 'Tuesday', 2: 'Wednesday',
3: 'Thursday', 4: 'Friday', 5: 'Saturday', 6: 'Sunday'
}
df['Request day'] = df['Request day'].map(weekday_map)
# Assign time slot (e.g. Morning, Afternoon)
df['Time slot'] = df['Request hour'].apply(get_time_period)
df['Time slot'] = df['Time slot'].astype('category')
# Display the Extracted Time Features
cols_to_show = ['Request timestamp', 'Request hour', 'Request day',
'Time slot']
existing_cols = [col for col in cols_to_show if col in df.columns]
print(df[existing_cols].head())
# Calculate trip duration as timedelta
df['Trip duration'] = df['Drop timestamp'] - df['Request timestamp']
# Convert timedelta to string just for readability
df['Trip duration'] = df['Trip duration'].apply(
lambda x: str(x).replace("0 days ", "") if pd.notna(x) else "00:00:00"
)
# Binary features
df['Is Completed'] = df['Status'] == 'Trip Completed'
df['Driver Available'] = df['Driver id'].apply(lambda x: True if pd.notna(x) and x > 0 else False)
# Extract just the date
df['Request Date'] = df['Request timestamp'].dt.date
# Calculate duration in minutes from timedelta
df['Trip Duration Mins'] = df['Trip duration'].apply(
lambda x: round(pd.Timedelta(x).total_seconds() / 60, 1) if pd.notna(x) else 0
)
return df
# ----------------------------------------------------------------
# Optional test block for standalone use
# ----------------------------------------------------------------
if __name__ == "__main__":
df = pd.read_csv("data/Uber Request Data.csv", sep="\t")
from src.data_cleaning_and_preprocessing import clean_data
df = clean_data(df)
df = engineer_features(df)
print(df[['Request timestamp', 'Drop timestamp', 'Trip duration', 'Trip Duration Mins']].head())