use pandrs::dataframe::DataFrameWindowExt;
use pandrs::error::Result;
use pandrs::series::{WindowExt, WindowOps};
use pandrs::{DataFrame, Series};
#[allow(clippy::result_large_err)]
#[allow(clippy::result_large_err)]
fn main() -> Result<()> {
println!("=== Comprehensive Window Operations Example ===\n");
println!("1. Creating Sample Data:");
let values = vec![
100.0, 102.0, 101.0, 103.0, 105.0, 104.0, 106.0, 108.0, 107.0, 109.0,
];
let dates = vec![
"2024-01-01",
"2024-01-02",
"2024-01-03",
"2024-01-04",
"2024-01-05",
"2024-01-06",
"2024-01-07",
"2024-01-08",
"2024-01-09",
"2024-01-10",
];
let mut df = DataFrame::new();
let date_series = Series::new(
dates.into_iter().map(|s| s.to_string()).collect(),
Some("Date".to_string()),
)?;
let value_series = Series::new(values.clone(), Some("Price".to_string()))?;
let price_series = value_series.to_string_series()?;
df.add_column("Date".to_string(), date_series)?;
df.add_column("Price".to_string(), price_series)?;
println!("Original Data:");
println!("{df:?}");
println!("\n=== Series-Level Window Operations ===\n");
println!("2. Rolling Window Operations (window=3):");
let value_series = Series::new(values.clone(), Some("Price".to_string()))?;
let rolling_mean = value_series.rolling(3)?.mean()?;
println!("Rolling Mean: {:?}", rolling_mean.values());
let rolling_sum = value_series.rolling(3)?.sum()?;
println!("Rolling Sum: {:?}", rolling_sum.values());
let rolling_std = value_series.rolling(3)?.std(1)?;
println!("Rolling Std: {:?}", rolling_std.values());
let rolling_min = value_series.rolling(3)?.min()?;
let rolling_max = value_series.rolling(3)?.max()?;
println!("Rolling Min: {:?}", rolling_min.values());
println!("Rolling Max: {:?}", rolling_max.values());
let rolling_median = value_series.rolling(3)?.median()?;
println!("Rolling Median: {:?}", rolling_median.values());
let rolling_q75 = value_series.rolling(3)?.quantile(0.75)?;
println!("Rolling 75th Percentile: {:?}", rolling_q75.values());
println!("\n3. Expanding Window Operations (min_periods=2):");
let expanding_mean = value_series.expanding(2)?.mean()?;
println!("Expanding Mean: {:?}", expanding_mean.values());
let expanding_std = value_series.expanding(2)?.std(1)?;
println!("Expanding Std: {:?}", expanding_std.values());
let expanding_min = value_series.expanding(2)?.min()?;
let expanding_max = value_series.expanding(2)?.max()?;
println!("Expanding Min: {:?}", expanding_min.values());
println!("Expanding Max: {:?}", expanding_max.values());
println!("\n4. Exponentially Weighted Moving Operations:");
let ewm_mean_span = value_series.ewm().span(3).mean()?;
println!("EWM Mean (span=3): {:?}", ewm_mean_span.values());
let ewm_mean_alpha = value_series.ewm().alpha(0.5)?.mean()?;
println!("EWM Mean (alpha=0.5): {:?}", ewm_mean_alpha.values());
let ewm_std = value_series.ewm().span(5).std(1)?;
println!("EWM Std (span=5): {:?}", ewm_std.values());
println!("\n5. Custom Aggregation Functions:");
let rolling_range = value_series.rolling(3)?.apply(|window| {
let min_val = window.iter().fold(f64::INFINITY, |a, &b| a.min(b));
let max_val = window.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));
max_val - min_val
})?;
println!("Rolling Range: {:?}", rolling_range.values());
let rolling_geomean = value_series.rolling(3)?.apply(|window| {
let product: f64 = window.iter().product();
product.powf(1.0 / window.len() as f64)
})?;
println!("Rolling Geometric Mean: {:?}", rolling_geomean.values());
println!("\n=== DataFrame-Level Window Operations ===\n");
println!("6. DataFrame Rolling Operations:");
let df_rolling_mean = df.rolling(3, "Price", "mean", Some("Price_Rolling_Mean"))?;
println!("DataFrame with Rolling Mean:");
println!("{df_rolling_mean:?}");
let df_rolling_std = df.rolling(3, "Price", "std", Some("Price_Rolling_Std"))?;
println!("\nDataFrame with Rolling Std:");
println!("{df_rolling_std:?}");
println!("\n7. DataFrame Expanding Operations:");
let df_expanding = df.expanding(2, "Price", "mean", Some("Price_Expanding_Mean"))?;
println!("DataFrame with Expanding Mean:");
println!("{df_expanding:?}");
println!("\n8. DataFrame EWM Operations:");
let df_ewm = df.ewm("Price", "mean", Some(3), None, Some("Price_EWM_Mean"))?;
println!("DataFrame with EWM Mean:");
println!("{df_ewm:?}");
println!("\n=== Advanced Window Configurations ===\n");
println!("9. Advanced Rolling Configurations:");
let rolling_min_periods = value_series.rolling(5)?.min_periods(3).mean()?;
println!(
"Rolling Mean (window=5, min_periods=3): {:?}",
rolling_min_periods.values()
);
let rolling_centered = value_series.rolling(5)?.center(true).mean()?;
println!(
"Centered Rolling Mean (window=5): {:?}",
rolling_centered.values()
);
println!("\n10. Performance Demonstration:");
demonstrate_performance_scenarios()?;
println!("\n11. Edge Cases and Error Handling:");
demonstrate_edge_cases()?;
println!("\n=== Comprehensive Window Operations Complete ===");
println!("\nNew capabilities implemented:");
println!("✓ Rolling windows with configurable parameters");
println!("✓ Expanding windows with minimum periods");
println!("✓ Exponentially weighted moving operations");
println!("✓ Custom aggregation functions");
println!("✓ DataFrame-level window operations");
println!("✓ Advanced window configurations");
println!("✓ Comprehensive statistical functions");
println!("✓ Performance optimizations");
println!("✓ Robust error handling");
Ok(())
}
#[allow(clippy::result_large_err)]
#[allow(clippy::result_large_err)]
fn demonstrate_performance_scenarios() -> Result<()> {
println!("--- Performance Scenarios ---");
let large_data: Vec<f64> = (0..1000)
.map(|i| 100.0 + (i as f64 * 0.1) + ((i as f64 * 0.01).sin() * 10.0))
.collect();
let large_series = Series::new(large_data, Some("LargeData".to_string()))?;
println!("Processing 1000 data points:");
let start = std::time::Instant::now();
let _rolling_mean = large_series.rolling(50)?.mean()?;
println!(" Rolling mean (window=50): {:?}", start.elapsed());
let start = std::time::Instant::now();
let _expanding_mean = large_series.expanding(10)?.mean()?;
println!(" Expanding mean (min_periods=10): {:?}", start.elapsed());
let start = std::time::Instant::now();
let _ewm_mean = large_series.ewm().span(20).mean()?;
println!(" EWM mean (span=20): {:?}", start.elapsed());
Ok(())
}
#[allow(clippy::result_large_err)]
#[allow(clippy::result_large_err)]
fn demonstrate_edge_cases() -> Result<()> {
println!("--- Edge Cases ---");
let empty_series: Series<f64> = Series::new(vec![], Some("Empty".to_string()))?;
match empty_series.rolling(3) {
Ok(rolling) => match rolling.mean() {
Ok(result) => println!("Empty series rolling mean: {} values", result.len()),
Err(e) => println!("Empty series rolling mean error: {e:?}"),
},
Err(e) => println!("Empty series rolling error: {e:?}"),
}
let single_series = Series::new(vec![42.0], Some("Single".to_string()))?;
match single_series.rolling(3) {
Ok(rolling) => {
let result = rolling.mean()?;
println!("Single value rolling mean: {:?}", result.values());
}
Err(e) => println!("Single value rolling error: {e:?}"),
}
let test_series = Series::new(vec![1.0, 2.0, 3.0], Some("Test".to_string()))?;
match test_series.rolling(0) {
Ok(_) => println!("Zero window size: Unexpectedly succeeded"),
Err(e) => println!("Zero window size error (expected): {e:?}"),
}
match test_series.rolling(2) {
Ok(rolling) => match rolling.quantile(1.5) {
Ok(_) => println!("Invalid quantile: Unexpectedly succeeded"),
Err(e) => println!("Invalid quantile error (expected): {e:?}"),
},
Err(e) => println!("Rolling creation error: {e:?}"),
}
match test_series.ewm().alpha(1.5) {
Ok(_) => println!("Invalid alpha: Unexpectedly succeeded"),
Err(e) => println!("Invalid alpha error (expected): {e:?}"),
}
Ok(())
}