提问人:Arkut 提问时间:9/24/2023 更新时间:9/24/2023 访问量:30
D3 地图仅显示一个县的空白/死区
D3 map showing a blank/dead area for only one county
问:
我更新了按 SNAP 参与划分的美国所有县的 D3 地图,以使用更新的数据(2017-2021 年 5 年 ACS)和更新的 topojson 文件(counties-alters-10m.json,来自 US Atlas,位于 Github 上:https://github.com/topojson/us-atlas)。除了一个县之外,它对所有县都很好:亚利桑那州的莫哈维县。
我检查了 Mohave County (04015) 的 FIPS 代码,该代码在 SNAP 数据和 topojson 文件中都是正确的——前导 0 显示和所有内容。
下面是 JavaScript 代码,它将所有县的集合分层,其中县集分为大都市区的县、小城市区的县和两者都不中的县,因此我可以添加按钮来打开/关闭每组县:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
active = d3.select(null);
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", zoomed);
var path = d3.geoPath();
var svg = d3.select("svg")
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("viewBox", "0 0 " + (width) + " " + (height))
.on("click", stopped, true);
var COLOR_COUNTS = 5;
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", reset);
var g = svg.append("g");
svg
.style("border", "2px solid #000")
.call(zoom);
var formatPercent = d3.format(".1%");
var formatPercentRnd = d3.format(".0%");
// Queue up datasets using d3 Queue
d3.queue()
.defer(d3.json, "./counties-albers-10m-min.json")
.defer(d3.tsv, "./snap_acs_2021_5yr-min.tsv")
.await(ready);
function ready(error, us, snap) {
if (error) throw error;
var rateById = {}; // Create empty object for holding dataset
var nameById = {};
var moeById = {};
var metroById = {};
var typeById = {};
var stRateById = {};
var stNameById = {};
var stMoeById = {};
var stRateMetById = {};
var stRateMicById = {};
var stRateRurById = {};
var stMoeMetById = {};
var stMoeMicById = {};
var stMoeRurById = {};
snap.forEach(function(d) {
rateById[d.county_fips] = d.pct_hh_snap; // Create property for each ID, give it value from rate
nameById[d.county_fips] = d.county;
moeById[d.county_fips] = d.pct_hh_snap_moe;
metroById[d.county_fips] = d.metroflg;
typeById[d.county_fips] = d.metrolabel;
stRateById[d.county_fips] = d.state_pct_hh_snap;
stNameById[d.county_fips] = d.state;
stMoeById[d.county_fips] = d.state_pct_hh_snap_moe;
stRateMetById[d.county_fips] = d.state_pct_hh_snap_metro;
stRateMicById[d.county_fips] = d.state_pct_hh_snap_micro;
stRateRurById[d.county_fips] = d.state_pct_hh_snap_rural;
stMoeMetById[d.county_fips] = d.state_pct_hh_snap_moe_metro;
stMoeMicById[d.county_fips] = d.state_pct_hh_snap_moe_micro;
stMoeRurById[d.county_fips] = d.state_pct_hh_snap_moe_rural;
});
var color = d3.scaleThreshold()
.domain([.05, .1, .15, .20, .25])
.range(d3.schemeGreens[6]);
g.selectAll("path")
.data(topojson.feature(us, us.objects.nation).features)
.enter().append("path")
.attr("class", "nation")
.attr("d", path);
g.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("d", path)
.attr("class", "counties")
.on("click", clicked)
.style("fill", function(d) {
return color(rateById[d.id]);
}).on("mousemove", function(d) {
var html = "";
html += "<div class=\"tooltip_kv\">";
html += "<span class=\"tooltip_key\">";
html += nameById[d.id] + ", " + stNameById[d.id];
html += " (" + typeById[d.id] + ")<br/><br/>"
html += (rateById[d.id] ? formatPercent(rateById[d.id]) : "");
html += " Hhlds w/ SNAP";
html += " (±";
html += (moeById[d.id] ? formatPercent(moeById[d.id]) : "");
html += ")<br/><br/>";
html += "Statewide:<br/> ";
html += (stRateById[d.id] ? formatPercent(stRateById[d.id]) : "");
html += " Overall (±";
html += (stMoeById[d.id] ? formatPercent(stMoeById[d.id]) : "");
html += ")<br/> ";
html += (stRateMetById[d.id] ? formatPercent(stRateMetById[d.id]) : "");
html += " Metro (±";
html += (stMoeMetById[d.id] ? formatPercent(stMoeMetById[d.id]) : "");
html += ")<br/> ";
html += (stRateMicById[d.id] ? formatPercent(stRateMicById[d.id]) : "");
html += " Small Town";
html += " (±";
html += (stMoeMicById[d.id] ? formatPercent(stMoeMicById[d.id]) : "");
html += ")<br/> ";
html += (stRateRurById[d.id] ? formatPercent(stRateRurById[d.id]) : "");
html += " Rural";
html += " (±";
html += (stMoeRurById[d.id] ? formatPercent(stMoeRurById[d.id]) : "");
html += ")";
html += "</span>";
html += "";
html += "</div>";
$("#tooltip-container").html(html);
$("#tooltip-container").show();
var coordinates = d3.mouse(this);
d3.select("#tooltip-container")
.style("top", (d3.event.pageY - 250) + "px")
.style("left", (d3.event.pageX - 250) + "px");
})
.on("mouseout", function() {
$console.log(d);
$("#tooltip-container").hide();
});
d3.select("#metro-county").on("click", function() {
var active = g.active ? false : true, newOpacity = active ? 0.1 : 1;
var newFill = active ? "#333" : "#ccc";
d3.selectAll("path")
.filter(function(d) { return metroById[d.id] == "metro" })
.style("opacity", newOpacity); // New Position
d3.select("#metro-county")
.style("background-color", newFill);
g.active = active;
});
d3.select("#rural-county").on("click", function() {
var active = g.active ? false : true, newOpacity = active ? 0.1 : 1;
var newFill = active ? "#333" : "#ccc";
d3.selectAll("path")
.filter(function(d) { return metroById[d.id] == "rural" })
.style("opacity", newOpacity); // New Position
d3.select("#rural-county")
.style("background-color", newFill);
g.active = active;
});
d3.select("#micro-county").on("click", function() {
var active = g.active ? false : true, newOpacity = active ? 0.1 : 1;
var newFill = active ? "#333" : "#ccc";
d3.selectAll("path")
.filter(function(d) { return metroById[d.id] == "micro" })
.style("opacity", newOpacity); // New Position
d3.select("#micro-county")
.style("background-color", newFill);
g.active = active;
});
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
g.append("path")
.datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b; }))
.attr("class", "counties")
.attr("d", path);
var colorLegend = d3.legendColor()
.labelFormat(d3.format(".1f"))
.scale(color)
.shapePadding(5)
.shapeWidth(50)
.shapeHeight(10)
.labels(["<5%", "5-<10%", "10-<15%", "15-<20%", "20-<25%", "25%+"])
.labelOffset(10)
.orient('horizontal')
.title("Percent of Households with SNAP (2017-2021)");
legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(550, 20)")
.style("font-size","12px")
.call(colorLegend);
};
function clicked(d) {
if (active.node() === this) return reset();
active.classed("active", false);
active = d3.select(this).classed("active", true);
var bounds = path.bounds(d),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2,
scale = Math.max(1, Math.min(8, 0.9 / Math.max(dx / width, dy / height))),
translate = [width / 2 - scale * x, height / 2 - scale * y];
svg.transition()
.duration(750)
.call( zoom.transform, d3.zoomIdentity.translate(translate[0],translate[1]).scale(scale) );
}
function reset() {
active.classed("active", false);
active = d3.select(null);
svg.transition()
.duration(750)
.call( zoom.transform, d3.zoomIdentity );
}
function zoomed() {
g.style("stroke-width", 1.5 / d3.event.scale + "px");
g.attr("transform", d3.event.transform);
}
function stopped() {
if (d3.event.defaultPrevented) d3.event.stopPropagation();
}
function round(value, precision) {
var multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
}
`
亚利桑那州西北部的莫哈维县是空白的。它应该被阴影为中等绿色,因为它的 12.8% 值在图例中属于 10-<15% 类别。
2015 年,这里也提出了类似的问题:县级组跳县,但没有得到任何回应。
我在 2023 年 6 月在这里问了这个问题:为什么我的 D3 地图显示一个县的空白/死区,但正确显示所有其他 3,140 个县?
当时我没有提供足够的细节,所以我再试一次。我创建了一个基本版本的地图,并将文件发布在这里:https://github.com/arkut/snapmap.git
这包括 html、css、javascript 和数据文件。如果这些文件(snap-counties.html - 忽略此文件除外)包含在 Web 服务器上彼此相同的文件夹中,则地图应显示并如下所示: SNAP 地图链接
我希望有人能帮忙。如果我应该在这里提供其他详细信息,请告诉我。
我创建了一个最小的可重现地图示例。它显示了与完整版地图相同的问题(其中包括许多 Wordpress html/css/javascript 代码,使整个页面看起来像 Wordpress 页面)。
答: 暂无答案
评论