You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据年龄数组动态生成区间并统计各区间人数?

动态生成年龄区间并统计人数用于饼图展示

问题背景

我在前端用饼图展示客户年龄占比,已获取所有客户年龄数组:

const ages = [12,42,23,42,12,65,75,12,43,54,12,53,24,23,54,64,76,12,42];

期望得到如下格式的统计结果:

const data = {
    labels: ['12-20', '21-40', '41-60', '61-76'],
    dataSet: [4, 6, 2, 5] // 各区间人数总和需等于原数组长度
}

之前尝试用四分位数固定划分4个区间,但数据量较少时区间数不合适,需要实现动态生成区间并统计人数的方案。

之前的固定四分位数代码:

const ages = [12, 42, 53, 12, 32, 12, 52, 66, 76, 87, 23, 12, 43, 12, 43, 54, 65].sort((a, b) => a - b);
const minAge = Math.min(...ages);
const maxAge = Math.max(...ages);
const q1 = ages[Math.floor(ages.length / 4)];
const q2 = ages[Math.floor(ages.length / 2)];
const q3 = ages[Math.floor(ages.length * 3 / 4)];
let firstRangeCount = 0;
let secondRangeCount = 0;
let thirdRangeCount = 0;
let fourthRangeCount = 0;
for (const age of ages) {
    if (age) {
        if (age <= q1) {
            firstRangeCount++;
        } else if (age <= q2) {
            secondRangeCount++;
        } else if (age <= q3) {
            thirdRangeCount++;
        } else {
            fourthRangeCount++;
        }
    }
}
const data = {
    labels: [
        `${minAge} - ${q1}`,
        `${q1} - ${q2}`,
        `${q2} - ${q3}`,
        `${q3} - ${maxAge}`,
    ],
    datasets: {
        label: 'Ages',
        data: [firstRangeCount, secondRangeCount, thirdRangeCount, fourthRangeCount],
    }
}

解决方案

下面提供几种动态生成区间的思路,可根据实际需求选择:

1. 基于数据量动态调整区间数

设定区间数的规则:比如数据量≤5时用2个区间,5-15用3个,15+用4个,也可自定义阈值。

代码示例:

function generateAgeData(ages) {
    const sortedAges = [...ages].sort((a, b) => a - b);
    if (sortedAges.length === 0) return { labels: [], dataSet: [] };
    
    const min = sortedAges[0];
    const max = sortedAges[sortedAges.length - 1];
    let binCount;

    // 根据数据量动态确定区间数
    if (sortedAges.length <= 5) {
        binCount = 2;
    } else if (sortedAges.length <= 15) {
        binCount = 3;
    } else {
        binCount = 4;
    }

    // 计算区间步长,向上取整保证覆盖最大值
    const binSize = Math.ceil((max - min) / binCount);
    const labels = [];
    const counts = new Array(binCount).fill(0);

    // 生成区间标签并统计人数
    for (let i = 0; i < binCount; i++) {
        const start = min + i * binSize;
        // 最后一个区间的结束值设为最大值,避免步长取整导致超出
        const end = i === binCount - 1 ? max : start + binSize - 1;
        labels.push(`${start}-${end}`);
        
        // 统计当前区间的人数
        counts[i] = sortedAges.filter(age => age >= start && age <= end).length;
    }

    return {
        labels: labels,
        dataSet: counts
    };
}

// 测试调用
const ages = [12,42,23,42,12,65,75,12,43,54,12,53,24,23,54,64,76,12,42];
const data = generateAgeData(ages);
console.log(data);

2. 使用Sturges'公式计算最优区间数

这是统计学中常用的确定分组数的公式,公式为:k = 1 + log2(n),其中n是数据量,结果向上取整。

代码示例:

function generateAgeData(ages) {
    const sortedAges = [...ages].sort((a, b) => a - b);
    const n = sortedAges.length;
    if (n === 0) return { labels: [], dataSet: [] };
    
    const min = sortedAges[0];
    const max = sortedAges[sortedAges.length - 1];
    // Sturges'公式计算区间数
    const binCount = Math.ceil(1 + Math.log2(n));
    const binSize = Math.ceil((max - min) / binCount);
    
    const labels = [];
    const counts = new Array(binCount).fill(0);

    for (let i = 0; i < binCount; i++) {
        const start = min + i * binSize;
        const end = i === binCount - 1 ? max : start + binSize - 1;
        labels.push(`${start}-${end}`);
        counts[i] = sortedAges.filter(age => age >= start && age <= end).length;
    }

    return {
        labels: labels,
        dataSet: counts
    };
}

// 测试
const ages = [12,42,23,42,12,65,75,12,43,54,12,53,24,23,54,64,76,12,42];
console.log(generateAgeData(ages));

3. 自定义区间阈值(适合业务场景明确的情况)

如果业务上有固定的年龄分段需求(比如少年、青年、中年、老年),可以动态判断是否合并区间:当某区间人数为0时,自动合并到相邻区间。

代码示例:

function generateAgeData(ages) {
    const ranges = [
        { start: 0, end: 20, label: '0-20' },
        { start: 21, end: 40, label: '21-40' },
        { start: 41, end: 60, label: '41-60' },
        { start: 61, end: 120, label: '61+' }
    ];

    // 统计各区间人数
    const countMap = ranges.map(range => {
        return {
            label: range.label,
            count: ages.filter(age => age >= range.start && age <= range.end).length
        };
    });

    // 过滤掉人数为0的区间(可选)
    const filtered = countMap.filter(item => item.count > 0);

    return {
        labels: filtered.map(item => item.label),
        dataSet: filtered.map(item => item.count)
    };
}

// 测试
const ages = [12,42,23,42,12,65,75,12,43,54,12,53,24,23,54,64,76,12,42];
console.log(generateAgeData(ages));

注意事项

  • 处理空数组:需要添加判断,避免报错
  • 区间边界:最后一个区间建议直接设为最大值,防止步长取整后超出实际最大年龄
  • 性能优化:如果数据量极大,filter方法可以换成单次遍历统计,提升效率

内容的提问来源于stack exchange,提问作者Juan Pedro Pont Vergès

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 13:24:23