登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go教程

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 的样本不能放入这个配置。

Histogram输入与区间约定的结构图
静态结构图:输入分组包含边界、样本与权重,区间分组说明左闭右开,接口分组关联计数对象;不是运行截图。

输入范围错误时,该函数不会默默丢弃样本,当前实现会 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 接受给定的有序边界。只是在做密度或视觉比较时,需要明确各区间宽度。

适合持续输入的在线累计吗?它适合对已整理的有序样本进行一次分箱汇总。持续输入需要自行管理批次、排序成本、累计状态与边界一致性,不能把重复调用自动理解为累加。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>