choropleth = {
const provinces = topojson.feature(vietnam, vietnam.objects.vn_iso_province),
country = topojson.mesh(vietnam, vietnam.objects.vn_iso_province, (a, b) => a === b)
const projection = d3.geoMercator()
.fitSize([width, width], provinces)
const path = d3.geoPath(projection)
const valueMap = new Map(data.map(d => [d.Province, +d.Value]))
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, width])
const uniqueProvinces = Array.from(
d3.group(provinces.features, d => d.properties.Name_EN).values(),
features => features.reduce((a, b) => d3.geoArea(a) > d3.geoArea(b) ? a : b)
);
const g = svg.append("g")
g.selectAll("path")
.data(provinces.features)
.join("path")
.attr("fill", d => {
const val = valueMap.get(d.properties.Name_EN)
return val != null ? color(val) : "#eee"
})
.attr("stroke", "lightgray")
.attr("d", path)
g.selectAll("text")
.data(uniqueProvinces)
.join("text")
.filter(d => valueMap.get(d.properties.Name_EN) != null)
.attr("x", d => projection(d3.geoCentroid(d))[0])
.attr("y", d => projection(d3.geoCentroid(d))[1])
.text(d => d.properties.Name_EN)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "central")
.attr("font-size", 5)
.attr("fill", "black")
.style("pointer-events", "none")
svg.append("path")
.datum(country)
.attr("fill", "none")
.attr("stroke", "gray")
.attr("d", path)
return svg.node()
}