philiprehberger-math_kit

Statistics, regression, interpolation, rounding modes, and moving averages for Ruby
Requirements
Installation
Add to your Gemfile:
gem "philiprehberger-math_kit"
Or install directly:
gem install philiprehberger-math_kit
Usage
require "philiprehberger/math_kit"
Statistics
Philiprehberger::MathKit::Stats.mean([1, 2, 3, 4, 5]) # => 3.0
Philiprehberger::MathKit::Stats.median([3, 1, 4, 1, 5]) # => 3.0
Philiprehberger::MathKit::Stats.mode([1, 2, 2, 3]) # => [2]
Philiprehberger::MathKit::Stats.variance([2, 4, 4, 4, 5, 5, 7, 9]) # => 4.0
Philiprehberger::MathKit::Stats.stddev([2, 4, 4, 4, 5, 5, 7, 9]) # => 2.0
Philiprehberger::MathKit::Stats.percentile([1, 2, 3, 4, 5], 50) # => 3.0
Philiprehberger::MathKit::Stats.sum([1, 2, 3]) # => 6
Philiprehberger::MathKit::Stats.range([1, 5, 3, 9, 2]) # => 8
Philiprehberger::MathKit::Stats.sum_of_squares([1, 2, 3]) # => 2.0
Interquartile Range
Philiprehberger::MathKit::Stats.iqr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # => 4.5
Summary Statistics
Philiprehberger::MathKit::Stats.describe([1, 2, 3, 4, 5])
# => { count: 5, mean: 3.0, median: 3.0, min: 1.0, max: 5.0,
# stddev: 1.58..., variance: 2.5, p25: 2.0, p50: 3.0, p75: 4.0 }
Weighted Mean
Philiprehberger::MathKit::Stats.weighted_mean([10, 20, 30], weights: [3, 1, 1])
# => 16.0
Histogram
Philiprehberger::MathKit::Stats.histogram([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], bins: 5)
# => [{ min: 1.0, max: 2.8, count: 2 }, { min: 2.8, max: 4.6, count: 2 }, ...]
Skewness and Kurtosis
Philiprehberger::MathKit::Stats.skewness([1, 1, 1, 2, 5, 10]) # => positive (right-skewed)
Philiprehberger::MathKit::Stats.kurtosis([2, 3, 4, 5, 6, 7]) # => near 0 (normal-like)
Confidence Intervals
data = [10, 12, 14, 16, 18]
lower, upper = Philiprehberger::MathKit::Stats.confidence_interval(data, level: 0.95)
# => [9.87, 18.13] (approximate)
Correlation and Covariance
Philiprehberger::MathKit::Stats.correlation([1, 2, 3, 4], [2, 4, 6, 8]) # => 1.0
Philiprehberger::MathKit::Stats.covariance([1, 2, 3, 4], [2, 4, 6, 8]) # => 3.333...
Data Normalization
Philiprehberger::MathKit::Stats.normalize([10, 20, 30]) # => [0.0, 0.5, 1.0]
Philiprehberger::MathKit::Stats.standardize([10, 20, 30, 40]) # => z-scores (mean=0, stddev=1)
Robust Statistics
Philiprehberger::MathKit::Stats.median_absolute_deviation([1, 1, 2, 2, 4, 6, 9]) # => 1.0
Philiprehberger::MathKit::Stats.trimmed_mean([1, 2, 3, 4, 100], trim: 0.2) # => 3.0
Philiprehberger::MathKit::Stats.winsorized_mean([1, 2, 3, 4, 100], trim: 0.2) # => less affected by outlier
Linear Regression
result = Philiprehberger::MathKit::Regression.linear([1, 2, 3, 4], [2, 4, 6, 8])
result.slope # => 2.0
result.intercept # => 0.0
result.r_squared # => 1.0
result.predict(5) # => 10.0
Interpolation
points = [[0, 0], [5, 10], [10, 20]]
Philiprehberger::MathKit::Interpolation.linear(points, 2.5) # => 5.0
Philiprehberger::MathKit::Interpolation.linear(points, 7.5) # => 15.0
Rounding
Philiprehberger::MathKit::Round.bankers(2.5) # => 2.0 (round half to even)
Philiprehberger::MathKit::Round.bankers(3.5) # => 4.0
Philiprehberger::MathKit::Round.ceiling(2.1) # => 3.0
Philiprehberger::MathKit::Round.floor(2.9) # => 2.0
Philiprehberger::MathKit::Round.truncate(2.9) # => 2.0
Philiprehberger::MathKit::Round.bankers(2.55, precision: 1) # => 2.6
Moving Averages
Philiprehberger::MathKit::MovingAverage.simple([1, 2, 3, 4, 5], window: 3) # => [2.0, 3.0, 4.0]
Philiprehberger::MathKit::MovingAverage.exponential([1, 2, 3, 4, 5], alpha: 0.5) # => [1.0, 1.5, 2.25, 3.125, 4.0625]
Numeric Helpers
Philiprehberger::MathKit::Numeric.factorial(5) # => 120
Philiprehberger::MathKit::Numeric.fibonacci(10) # => 55
Philiprehberger::MathKit::Numeric.gcd(12, 18) # => 6
Philiprehberger::MathKit::Numeric.lcm(4, 6) # => 12
Philiprehberger::MathKit::Numeric.clamp(42, 0, 10) # => 10
API
Stats
| Method | Description |
|---|
.mean(values) | Arithmetic mean |
.median(values) | Median (middle value or average of two middle) |
.mode(values) | Mode(s) as array |
.variance(values, population: true) | Population or sample variance |
.stddev(values, population: true) | Standard deviation |
.percentile(values, p) | Percentile (0-100) with linear interpolation |
.iqr(values) | Interquartile range (Q3 - Q1) |
.sum(values) | Sum of values |
.sum_of_squares(values) | Sum of squared deviations from the mean (0.0 for empty/single input) |
.range(values) | Max - min |
.skewness(values) | Sample skewness (Fisher-Pearson) |
.kurtosis(values) | Sample excess kurtosis (Fisher definition) |
.confidence_interval(values, level: 0.95) | Confidence interval for the mean |
.correlation(xs, ys) | Pearson correlation coefficient |
.covariance(xs, ys) | Sample covariance |
.normalize(values) | Min-max normalization to 0..1 |
.standardize(values) | Z-score standardization (mean=0, stddev=1) |
.median_absolute_deviation(values) | Median absolute deviation |
.trimmed_mean(values, trim: 0.1) | Trimmed mean (remove fraction from each end) |
.winsorized_mean(values, trim: 0.1) | Winsorized mean (clamp extremes) |
.describe(values) | Summary statistics hash (count, mean, median, min, max, stddev, percentiles) |
.histogram(values, bins: 10) | Frequency distribution as array of bin hashes |
.weighted_mean(values, weights:) | Weighted arithmetic mean |
Regression
| Method | Description |
|---|
.linear(xs, ys) | Ordinary least squares linear regression |
Result#slope | Slope of the fitted line |
Result#intercept | Y-intercept of the fitted line |
Result#r_squared | Coefficient of determination (0 to 1) |
Result#predict(x) | Predict y for a given x |
Interpolation
| Method | Description |
|---|
.linear(points, x) | Linear interpolation between sorted points |
Round
| Method | Description |
|---|
.bankers(value, precision: 0) | Banker's rounding (round half to even) |
.ceiling(value, precision: 0) | Round up |
.floor(value, precision: 0) | Round down |
.truncate(value, precision: 0) | Truncate toward zero |
MovingAverage
| Method | Description |
|---|
.simple(values, window:) | Simple moving average |
.exponential(values, alpha:) | Exponential moving average |
Numeric
| Method | Description |
|---|
.factorial(n) | Factorial of a non-negative integer |
.fibonacci(n) | N-th Fibonacci number (0-indexed) |
.gcd(a, b) | Greatest common divisor of two integers |
.lcm(a, b) | Least common multiple of two integers |
.clamp(value, min, max) | Clamp a numeric value between min and max |
Development
bundle install
bundle exec rspec
bundle exec rubocop
Support
If you find this project useful:
⭐ Star the repo
🐛 Report issues
💡 Suggest features
❤️ Sponsor development
🌐 All Open Source Projects
💻 GitHub Profile
🔗 LinkedIn Profile
License
MIT