提问人:Dónal 提问时间:7/30/2014 最后编辑:Dónal 更新时间:7/30/2014 访问量:744
从数据库生成直方图
generate histogram from database
问:
在MySQL数据库中,有一个包含单个数字列的表。我想将这些值的分布绘制为条形图/直方图,并满足以下要求:value
- 图表中最多应有 N 根柱线(区间)
- 每个条形的宽度(X 轴范围)应均匀,每个条形的高度应反映此间隔中的值数。
- 柱线的端点应出现在整数处。我知道这是一个相当模糊的要求,但希望下面的例子能说明我的意思
- 间隔应该是连续的,例如,下一个间隔应该从前一个间隔结束的地方开始
- 理想情况下,应该可以通过单个查询检索数据
- 计数(y 轴值)为 0 的间隔是可以的
- 如果第一个区间的下限小于最小值和/或最后一个区间的上限大于最大值,则可以
value
value
例
如果 N = 3,并且表包含以下数据
+------------+
| value |
+------------+
| -49.2 |
| -28.2 |
| 13.3 |
| 23.3 |
| 51.4 |
| 77.9 |
+------------+
在检查时,很容易看出区间满足此数据集的要求和 N 的值。{-50..0, 0..50, 50..100}
但是,我正在努力提出一个适用于任何 N 值和任何数据集的通用解决方案。这是我到目前为止尝试过的:
计算间隔宽度
通过以下查询获取最大值和最小值value
SELECT min(value), max(value), count(*) FROM my_table
然后将结果传入这个 (Groovy/Java) 方法,以计算每个间隔的宽度
// intervalCount is what I've referred to as "N"
static Integer getRoundedIntervalSize(Double min, Double max, Integer intervalCount) {
Number intervalSize = Math.ceil((max - min) / intervalCount)
Integer roundingScale = Math.log10(intervalSize) - 1
Number roundNearest = 10 ** roundingScale
// round up the interval size to the nearest roundNearest
Number intervalDelta = roundNearest - (intervalSize % roundNearest)
intervalSize + intervalDelta
}
获取频率分布
然后,我使用以下查询(将 替换为 返回的值)来获取每个区间中的值数getRoundedIntervalSize
:groupSize
SELECT floor(value / :groupSize) * :groupSize as groupLowerLimit,
count(*) as groupCount
FROM my_table
GROUP BY groupLowerLimit
ORDER BY groupLowerLimit ASC
这将返回每个间隔的下限和每个间隔中的值数,这就是我构建频率分布所需的全部内容。
缺点
尽管当数据集相对均匀分布时,这种方法相当有效,但当情况并非如此时,它会导致区间具有不同的宽度或不连续。此外,当数据集的范围很小(例如,所有值都在 1 到 4 之间)而 N 很大(例如 30 个)时,生成的间隔数往往比 N 小得多。
有没有更好的方法来解决这个问题,满足上述要求?
答:
0赞
injecteer
7/30/2014
#1
我尝试了几个查询(我使用了一个带有一些坐标的表)
获取最小值和柱线大小:
select min( lng ) as min, ( max( lng ) - min( lng ) ) / ? as interval from address
获取分发。这些条形的编号从 0 到 N,当然可能有间隙
select floor( abs( lng - :min ) / :interval ) as ix, count(*) from address group by ix order by ix
的输出如下所示:N = 30
ix count
0 31
18 10149
20 36185
21 5443
24 1
29 3
为了填补空白,你需要一个时髦的单行本:
def metrics = run1stQuery(..., n )
def results = run2ndQuery(.., metrics )
def fullResults = (0..n).collect{ results[ it ] ?: metrics.min } // adjust the missing value
因此,您应该获得任何 N 和最小/最大值的频率组。
HTH型
评论
0赞
Dónal
7/30/2014
据推测,这并不能满足柱线(区间)的上限和下限为整数的要求?此外,调整每个条形宽度的时髦单行似乎意味着它们不会有统一的宽度?
0赞
injecteer
7/30/2014
“整数”的要求非常棘手,并迫使您具有不均匀的间隔。不,单行只是用 0 或一些默认值填充缺失的条形
0赞
injecteer
7/30/2014
要实现“整数”要求,第 0 根柱线必须在最小值之前开始,第 N 根柱线在最大值之后结束
0赞
Dónal
7/30/2014
如果第 0 根柱线在最小值之前开始和/或最后一根柱线在最大值之后结束,那没关系 - 我会将此信息添加到我的帖子中
0赞
injecteer
7/30/2014
顺便说一句,“整数”应该像 1234 还是 1200 或 1000?在后一种情况下,您可以使用 log10() 技巧
上一个:用于此的线性时间解决方案
评论