D3.js如何筛选d3.csv加载的数据,仅保留出现次数排名前n的结果
D3.js 奥运奖牌数据Top15国家筛选方案
核心优化思路
原有实现需要为每个国家单独遍历全量数据做过滤,时间复杂度为O(n*m),数据量较大时性能损耗明显。优化方案仅需单次遍历全量数据完成国家计数,结合排序取前15,整体时间复杂度为O(n + m log m),效率更高。
实现代码
步骤1:统计各国出现次数
使用d3.rollup单次遍历完成分组计数:
// 入参为已按年份筛选后的data const countryCountMap = d3.rollup( data, group => group.length, // 每个国家分组的计数(即奖牌获得次数) item => item.Country // 按国家字段分组 )
步骤2:排序取Top15国家
将统计结果转为数组后排序,截取前15位:
const top15CountryList = Array.from(countryCountMap) .sort((a, b) => b[1] - a[1]) // 按计数降序排列,奖牌数多的在前 .slice(0, 15) // 取前15个国家 .map(item => item[0]) // 仅提取国家名用于后续过滤
步骤3:过滤得到绘图数据
仅保留前15国家的原始数据用于绘图:
const finalChartData = data.filter(item => top15CountryList.includes(item.Country))
额外说明
如果柱状图的Y轴直接展示各国奖牌总数,可直接使用排序后的Array.from(countryCountMap).sort((a, b) => b[1] - a[1]).slice(0,15)作为绘图绑定数据,无需再过滤原始数据,每一项的结构为[国家名, 奖牌总数],可直接读取映射到坐标轴。
如果使用的是v6及以下版本的D3,没有内置d3.rollup,可以用d3.nest实现同等逻辑:
const countryCount = d3.nest() .key(d => d.Country) .rollup(v => v.length) .entries(data) const top15CountryList = countryCount .sort((a, b) => b.value - a.value) .slice(0,15) .map(d => d.key)
内容的提问来源于stack exchange,提问作者Kevin Goodenough
相关产品推荐
相关产品推荐

