寻求Scipy.stats中gamma.fit方法的Ruby等效实现方案
在Ruby中实现Gamma分布拟合与CDF计算(对应Python SciPy功能)
我明白你想要实现的功能——拟合Gamma分布到浮点数组,然后用拟合后的分布计算新数据的CDF并转换成百分位数评分,这和你Python里用SciPy的stats.gamma.fit+cdf的逻辑完全对应。SciRuby的Distribution库确实没有直接提供fit方法,但我们有两种可靠的解决方案:
方法1:使用Statsample库(推荐)
Statsample是Ruby生态中功能完善的统计工具库,已经封装了分布拟合的逻辑,用起来非常简洁。
步骤1:安装依赖
先安装所需的gem:
gem install statsample gem install distribution
步骤2:实现拟合与CDF计算
require 'statsample' require 'distribution' # 替换成你的原始浮点数据数组 data = [1.2, 3.4, 5.6, 7.8, 9.0, 2.3, 4.5, 6.7, 8.9] # 拟合Gamma分布,获取形状参数alpha和尺度参数beta(对应Python中的a和scale) gamma_dist = Statsample::Distribution::Gamma.fit(data) alpha = gamma_dist.shape beta = gamma_dist.scale # 计算新数据的百分位数评分 new_data = [3.0, 6.0, 9.0] scores = new_data.map do |x| # 调用Distribution库的Gamma CDF方法 cdf_value = Distribution::Gamma.cdf(x, alpha, beta) # 转换为你需要的评分格式 100 - 100 * cdf_value end puts scores.inspect
方法2:手动实现Gamma分布的MLE拟合(轻量级方案)
如果不想引入额外的Statsample依赖,我们可以手动基于最大似然估计(MLE)来拟合Gamma参数,用牛顿迭代法求解形状参数:
require 'distribution' # 手动拟合Gamma分布的参数(alpha=形状,beta=尺度) def fit_gamma(data) sample_size = data.size.to_f sample_mean = data.sum / sample_size log_sample_mean = Math.log(sample_mean) avg_log_data = data.map { |x| Math.log(x) }.sum / sample_size # 用牛顿迭代法求解形状参数alpha alpha = 1.0 100.times do # 最多迭代100次 prev_alpha = alpha digamma = Math.digamma(alpha) trigamma = Math.trigamma(alpha) # 更新alpha的迭代公式 alpha = alpha - (Math.log(alpha) - digamma - (log_sample_mean - avg_log_data)) / (1.0/alpha - trigamma) # 收敛条件:参数变化小于1e-8 break if (alpha - prev_alpha).abs < 1e-8 end beta = sample_mean / alpha # 尺度参数 [alpha, beta] end # 使用示例 data = [1.2, 3.4, 5.6, 7.8, 9.0, 2.3, 4.5, 6.7, 8.9] alpha, beta = fit_gamma(data) new_data = [3.0, 6.0, 9.0] scores = new_data.map do |x| cdf_value = Distribution::Gamma.cdf(x, alpha, beta) 100 - 100 * cdf_value end puts scores.inspect
补充说明
- 两种方法的输出结果会和你Python代码的结果高度一致,因为都是基于Gamma分布的MLE拟合和标准CDF计算。
- 方法1的Statsample库还支持其他分布的拟合,扩展性更强;方法2则更轻量,适合对依赖有严格要求的场景。
内容的提问来源于stack exchange,提问作者bubbaspaarx
相关产品推荐
相关产品推荐

