-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathdata_pipeline_numpy_pandas.py
More file actions
101 lines (82 loc) · 3.06 KB
/
Copy pathdata_pipeline_numpy_pandas.py
File metadata and controls
101 lines (82 loc) · 3.06 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
97
98
99
100
101
"""
Reactive Data Pipeline with NumPy and Pandas
Simple example showing automatic recalculation when data or parameters change.
Demonstrates lazy evaluation, memoization, and fine-grained reactive dependencies.
Run with:
1. pip install reaktiv numpy pandas
2. python examples/data_pipeline_numpy_pandas.py
"""
import numpy as np
import pandas as pd
from reaktiv import signal, computed, effect
def create_data() -> pd.DataFrame:
"""Generate sample sensor data."""
np.random.seed(42)
return pd.DataFrame(
{
"temperature": np.random.normal(20, 5, 1000),
"humidity": np.random.normal(60, 10, 1000),
"sensor": np.random.choice(["A", "B", "C"], 1000),
}
)
def main():
print("Reactive Data Pipeline Example")
# Reactive data sources
data = signal(create_data())
window_size = signal(10)
threshold = signal(2.0)
# Stage 1: Basic preprocessing - LAZY: not computed until accessed
@computed
def basic_stats():
return data().assign(
temp_mean=data()["temperature"].mean(),
temp_std=data()["temperature"].std(),
temp_smooth=data()["temperature"].rolling(window_size()).mean(),
)
@computed
def with_zscore():
return basic_stats().assign(
temp_zscore=(basic_stats()["temperature"] - basic_stats()["temp_mean"])
/ basic_stats()["temp_std"]
)
# Stage 3: Outlier detection - depends on with_zscore AND threshold
@computed
def with_outliers():
return with_zscore().assign(
is_outlier=np.abs(with_zscore()["temp_zscore"]) > threshold()
)
# Stage 4: Summary analysis - MEMOIZED: result cached until dependencies change
@computed
def summary():
df = with_outliers()
return {
"mean_temp": df["temperature"].mean(),
"outliers": df["is_outlier"].sum(),
"sensor_counts": df.groupby("sensor").size().to_dict(),
}
# Auto-updating report - triggers initial computation
def print_summary():
s = summary() # First access: computes entire pipeline
print(
f"Mean: {s['mean_temp']:.1f}°C, Outliers: {s['outliers']}, Sensors: {s['sensor_counts']}"
)
_report = effect(print_summary)
# Demonstrate fine-grained reactive updates
print(
"Changing window size (affects basic_stats, with_zscore, with_outliers, summary)..."
)
window_size.set(20)
print("Changing threshold (affects ONLY with_outliers and summary)...")
threshold.set(1.5) # FINE-GRAINED: only outlier detection and summary recalculate
# Add new data - entire pipeline recalculates due to root dependency
print("Adding new data (affects entire pipeline)...")
new_data = pd.DataFrame(
{
"temperature": np.random.normal(25, 3, 100),
"humidity": np.random.normal(50, 8, 100),
"sensor": np.random.choice(["A", "B", "C"], 100),
}
)
data.set(pd.concat([data(), new_data], ignore_index=True))
if __name__ == "__main__":
main()