Go Gonum stat 怎样按给定边界生成直方图计数
来源:17golang原创
时间:2026-10-30 22:31:57 219浏览 收藏
Go Gonum 的 stat.Histogram(nil, dividers, x, nil) 可以按给定边界生成直方图计数。先让边界与样本都按升序排列,并保证所有样本处于从首边界开始、到末边界之前的范围;每个区间采用左闭右开规则,返回长度为边界数减一的 []float64。
官方地址:https://www.gonum.org/
确定固定边界适合的统计问题
做耗时区间报表时,我更倾向于先固定区间含义,再选择统计函数:不同日期都使用相同边界,读者才方便比较。这个判断适合已有业务分档的场景,并不表示所有数据分析都应该使用固定分箱,也不说明这种做法有新的流行趋势。
Histogram 只汇总区间中的样本数或权重,不负责自动选箱、画图或解释数据分布。报表维护者和数据处理开发者可以共用一份边界定义;若两端各自自动推导边界,即使计数正确,图表也可能无法直接对照。
准备边界与有序样本
将边界保存在 dividers 中,例如 0、10、20、40 对应 [0,10)、[10,20)、[20,40)。样本 x 必须有序。内部边界上的值进入右侧区间,末边界本身不属于最后一个区间,因此值为 40 的样本不能放入这个配置。

输入范围错误时,该函数不会默默丢弃样本,当前实现会 panic。对于业务入口,我会先做明确的范围处理:要么拒绝,要么由上层将越界值单独归档并公开记录数量。不要先悄悄过滤,再把剩余计数称为全部样本分布。
nil 权重代表每个样本贡献一;非 nil 权重必须与样本数量相同。count 可为 nil,或长度恰好为 len(dividers)-1。上述约定可参考Histogram 官方文档。
封装普通计数并解释端点
下面用 Counts 封装无权重计数:复制样本以免排序改变调用方数据,拒绝 NaN、无穷值、越界值与重复边界,再调用 Histogram。严格递增是这个封装额外采用的业务约定,避免出现没有宽度的区间。
package main
import (
"fmt"
"math"
"sort"
"gonum.org/v1/gonum/stat"
)
// Counts 统计有限样本,不修改调用方切片;边界采用严格递增约定。
func Counts(raw, edges []float64) ([]float64, error) {
if len(edges) 0 && v = edges[len(edges)-1] {
return nil, fmt.Errorf("样本超出有效区间")
}
}
sort.Float64s(x)
return stat.Histogram(nil, edges, x, nil), nil
}
func main() {
// 四个边界形成三个区间,nil 权重表示每个样本贡献一。
edges := []float64{0, 10, 20, 40}
raw := []float64{27, 10, 2, 20, 9, 10, 39}
counts, err := Counts(raw, edges)
if err != nil {
panic(err) // 演示入口保留输入错误,不输出误导性的计数。
}
fmt.Println(counts)
}
按照区间规则手工推导,[0,10) 中是 2、9,共两个;[10,20) 中有两个 10,共两个;[20,40) 中是 20、27、39,共三个,因此计数应为 2、2、3。这是按规则推算的预期值,本文没有把程序执行结果或终端截图作为依据。
| 样本条件 | 本例归属或处理 |
|---|---|
| 等于 0 | 进入第一个区间 |
| 等于 10 | 进入 [10,20) |
| 等于 20 | 进入 [20,40) |
| 等于 40 | 被 Counts 拒绝 |
| 空样本 | 有效边界下得到全零计数 |
如果业务必须覆盖当前最大值,应在设计边界时给它留出合法上界。不要机械地对所有浮点数据加一:数据尺度与测量精度可能不同。应先确定业务区间定义,再让数据范围与定义一致。
保持权重与样本配对
带权重时,输出的是每个区间的权重和。比如样本 2、9、10、10、20、27、39 分别配权重 1、2、1、3、2、1、4,三个区间手工可算得 3、4、7。非整数权重也会产生非整数结果,因此返回类型是 []float64。
真正容易出错的是排序:如果原始 x 尚未排序,不能只 sort.Float64s(x) 而让 weights 原地不动。这样值和权重会错配。应将每个样本与其权重组成配对对象,按样本值排序,再同步拆出 x 和 weights,或者使用能同时重排两者的工具。

若想把权重解释为概率或频次,我会在业务层要求它们有限且非负,并检查总权重大于零。Histogram 的求和接口本身不能代替这些统计意义上的约束。
选择归一化和复用方式
Histogram 返回原始区间计数或权重和。无权重时,区间概率质量可由 count[j] 除以样本总数取得;概率密度还要再除以区间宽度 dividers[j+1]-dividers[j]。本例最后一个区间宽度是前两个的两倍,不能将柱高直接当作密度比较。
对于有效、全部在范围内的无权重样本,计数总和应等于样本数;非负带权重数据则应等于总权重,浮点计算采用适当容差。空数据或零总权重不应继续做除法。这些观察指标能帮助解释报表含义,不构成性能测量。
复用 count 会累加吗?不会。当前实现先清零 count,再统计本次数据。复用是重用切片空间;若要合并多个批次,应另有累计数组,按相同边界逐项求和。实现见Gonum stat 源码。
最后一个区间包含右端点吗?不包含。所有区间都遵循左闭右开,最大样本必须小于末边界。
必须用等宽边界吗?不必,Histogram 接受给定的有序边界。只是在做密度或视觉比较时,需要明确各区间宽度。
适合持续输入的在线累计吗?它适合对已整理的有序样本进行一次分箱汇总。持续输入需要自行管理批次、排序成本、累计状态与边界一致性,不能把重复调用自动理解为累加。
-
860 收藏
-
843 收藏
-
826 收藏
-
809 收藏
-
792 收藏
-
364 收藏
-
263 收藏
-
397 收藏
-
108 收藏
-
349 收藏
-
350 收藏
-
297 收藏
-
346 收藏
-
451 收藏
-
248 收藏
-
234 收藏
-
296 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习