在MySQL数据库中,有一个包含单个数字value
列的表。我想将这些值的分布绘制为具有以下要求的条形图/直方图:
value
和/或最后一个间隔的上限大于最大value
如果N = 3且表包含以下数据
+------------+
| value |
+------------+
| -49.2 |
| -28.2 |
| 13.3 |
| 23.3 |
| 51.4 |
| 77.9 |
+------------+
在检查时,很容易看到间隔{-50..0, 0..50, 50..100}
满足此数据集的要求和N的值。
然而,我正在努力想出一个适用于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 :(得分:0)
我尝试了几个查询(我使用了带有一些坐标的表格)
获得最小值和条形尺寸:
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