1 | *//! Regression analysis* |

2 | |

3 | **use** **crate**::stats::bivariate::Data; |

4 | **use** **crate**::stats::float::Float; |

5 | |

6 | */// A straight line that passes through the origin `y = m * x`* |

7 | #[derive(Clone, Copy)] |

8 | **pub** **struct** Slope<A>(**pub** A) |

9 | **where** |

10 | A: Float; |

11 | |

12 | **impl**<A> Slope<A> |

13 | **where** |

14 | A: Float, |

15 | { |

16 | */// Fits the data to a straight line that passes through the origin using ordinary least* |

17 | */// squares* |

18 | *///* |

19 | */// - Time: `O(length)`* |

20 | **pub** **fn** fit(data: &Data<'_, A, A>) -> Slope<A> { |

21 | **let** xs = data.0; |

22 | **let** ys = data.1; |

23 | |

24 | **let** xy = **crate**::stats::dot(xs, ys); |

25 | **let** x2 = **crate**::stats::dot(xs, xs); |

26 | |

27 | Slope(xy / x2) |

28 | } |

29 | |

30 | */// Computes the goodness of fit (coefficient of determination) for this data set* |

31 | *///* |

32 | */// - Time: `O(length)`* |

33 | **pub** **fn** r_squared(&self, data: &Data<'_, A, A>) -> A { |

34 | **let** _0 = A::cast(`0`); |

35 | **let** _1 = A::cast(`1`); |

36 | **let** m = self.0; |

37 | **let** xs = data.0; |

38 | **let** ys = data.1; |

39 | |

40 | **let** n = A::cast(xs.len()); |

41 | **let** y_bar = **crate**::stats::sum(ys) / n; |

42 | |

43 | **let** **mut** ss_res = _0; |

44 | **let** **mut** ss_tot = _0; |

45 | |

46 | **for** (&x, &y) **in** data.iter() { |

47 | ss_res = ss_res + (y - m * x).powi(`2`); |

48 | ss_tot = ss_res + (y - y_bar).powi(`2`); |

49 | } |

50 | |

51 | _1 - ss_res / ss_tot |

52 | } |

53 | } |

54 | |