D3JS绘制GeoJSON地图仅首个区域有值其余为null/undefined问题求助
可能诱因
- 括号配对错误导致名称映射逻辑只执行了部分:从现有代码的缩进和括号位置看,日期、年龄组的筛选逻辑被写在了疫苗数据名称映射的
vaccines.forEach循环内部,导致仅第一个疫苗数据项完成了名称匹配就触发了筛选,剩余未做名称映射的疫苗数据直接被过滤,最终只剩1条可匹配的有效记录。 - 名称匹配规则不严:虽然做了PHU名称映射,但未处理映射后名称与GeoJSON中
PHU_NAME_E字段的大小写、首尾空格、特殊符号差异,比如一方带后缀另一方不带、大小写不一致都会导致匹配失败。 - 筛选规则过滤了大部分有效数据:新增的年龄组、日期筛选逻辑可能存在参数不匹配问题:比如
selectedOption的值与CSV中Agegroup字段的格式不统一(如CSV存的是「12-17」,传入的筛选值是「12至17岁」),或者maxDays设置过小,导致筛选后仅剩余1个PHU的有效记录。 - 数据重复覆盖问题:若同一PHU在疫苗数据中存在多条符合筛选条件的记录,当前遍历赋值逻辑会直接覆盖之前的数值,若最后一条记录数值为空也会导致最终
rate为undefined。
解决建议
- 先修正代码结构:将日期、年龄组的筛选逻辑移到名称映射的
vaccines.forEach循环外部,确保所有疫苗数据先完成名称替换,再执行筛选操作,示例修正逻辑如下:
// 先完成所有疫苗数据的名称映射 vaccines.forEach (function(v) { phu1phu2.forEach(function(d) { if (v["PHU name"] == d["PHU name"]) { v["PHU name"] = d.Reporting_PHU; } }) }) // 名称映射完成后再执行筛选 vaccines = vaccines.filter(function(v) { var keyDate = parseDate(v.Date); var daysDiff = d3.timeDay.count(keyDate, filterDate); return daysDiff <= maxDays; }) vaccines = vaccines.filter(function(v) { return v.Agegroup == selectedOption; })
- 优化名称匹配规则:匹配时统一将两个字段转为全小写/全大写,同时去除首尾空格,避免格式差异导致匹配失败,示例匹配逻辑:
if (phu.properties.PHU_NAME_E.trim().toUpperCase() === v["PHU name"].trim().toUpperCase()) { phu.properties.rate = 100 * (v.Percent_fully_vaccinated); phu.properties.count = 100 * (v.Percent_at_least_one_dose); }
- 增加调试日志排查筛选结果:在筛选逻辑执行完成后打印筛选后的疫苗数据列表,确认是否包含所有PHU的记录:
console.log('筛选后有效数据:', vaccines.map(item => item["PHU name"]))
如果打印结果仅包含1个PHU,说明筛选逻辑存在参数错误,逐一校验selectedOption、maxDays、parseDate逻辑的正确性即可。
- 优化匹配逻辑避免双层循环:将疫苗数据转为以PHU名称为键的映射表,提升匹配效率的同时也便于排查未匹配的PHU:
const vaxMap = new Map(vaccines.map(v => [v["PHU name"].trim().toUpperCase(), v])) PHUs.forEach(phu => { const vaxData = vaxMap.get(phu.properties.PHU_NAME_E.trim().toUpperCase()) if (vaxData) { phu.properties.rate = 100 * (vaxData.Percent_fully_vaccinated); phu.properties.count = 100 * (vaxData.Percent_at_least_one_dose); } })
内容的提问来源于stack exchange,提问作者PatriciaW
相关产品推荐
相关产品推荐

