-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata_generator.py
More file actions
72 lines (57 loc) · 2.88 KB
/
Copy pathdata_generator.py
File metadata and controls
72 lines (57 loc) · 2.88 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
import pandas as pd
import numpy as np
import os
def generate_synthetic_data(num_meters=50, days=7):
"""
Generates synthetic 15-minute interval smart meter data.
"""
print(f"Generating synthetic data for {num_meters} meters over {days} days...")
# 15-minute intervals
date_rng = pd.date_range(start='2024-01-01', end=f'2024-01-{1+days}', freq='15min', inclusive='left')
data = []
for i in range(num_meters):
meter_id = f"MTR_{1000 + i}"
# Base consumption pattern (daily seasonality)
time_of_day = date_rng.hour + date_rng.minute / 60.0
# Peak around 18:00 to 22:00, low at night
base_consumption = 0.5 + 1.5 * np.sin(np.pi * (time_of_day - 6) / 12)
base_consumption = np.clip(base_consumption, 0.1, 5.0)
# Add random noise
noise = np.random.normal(0, 0.2, len(date_rng))
consumption = base_consumption + noise
consumption = np.clip(consumption, 0, None) # Ensure non-negative
df = pd.DataFrame({
'Timestamp': date_rng,
'Meter_ID': meter_id,
'Consumption_kWh': consumption,
'Is_Anomaly': 0,
# Generate a mock Grid Stress Score for the map later (0-100)
'Grid_Stress': np.random.uniform(20, 80, len(date_rng))
})
# Introduce anomalies (e.g. sudden drop simulating tampering or outage)
if np.random.rand() < 0.2: # 20% of meters have anomalies
anomaly_start_idx = np.random.randint(len(df) // 2, len(df) - 20)
anomaly_duration = np.random.randint(4, 16) # 1 to 4 hours
df.loc[anomaly_start_idx:anomaly_start_idx+anomaly_duration, 'Consumption_kWh'] *= 0.1 # 90% drop
df.loc[anomaly_start_idx:anomaly_start_idx+anomaly_duration, 'Is_Anomaly'] = 1
df.loc[anomaly_start_idx:anomaly_start_idx+anomaly_duration, 'Grid_Stress'] = np.random.uniform(80, 100, anomaly_duration + 1)
data.append(df)
final_df = pd.concat(data, ignore_index=True)
# Also create a mock metadata file for the map (lat, lon for each hash)
lat_center = 12.9716 # Bangalore lat
lon_center = 77.5946 # Bangalore lon
metadata = []
for i in range(num_meters):
meter_id = f"MTR_{1000 + i}"
# Randomize locations around Bangalore
lat = lat_center + np.random.normal(0, 0.05)
lon = lon_center + np.random.normal(0, 0.05)
metadata.append({'Meter_ID': meter_id, 'Latitude': lat, 'Longitude': lon})
meta_df = pd.DataFrame(metadata)
# Save to data directory
os.makedirs('data', exist_ok=True)
final_df.to_csv('data/raw_interval_data.csv', index=False)
meta_df.to_csv('data/raw_meter_metadata.csv', index=False)
print("Raw data generated and saved to data/ directory.")
if __name__ == "__main__":
generate_synthetic_data()