Map 创建正确显示分位数类范围值和配色方案中关联颜色的choropleth贴图图例?
我是一个新手程序员,正在尝试制作一个交互式choropleth地图。在获得了关于几个问题的帮助之后,最后一个大问题是地图图例不正确。图例应该为每个分位数类别显示不同的颜色,但到目前为止,将最暗的颜色与第二大类别关联(而不是仅为最大类别),然后为最大类别重复该颜色。此外,对于大多数可用的分位数选择选项,图例中没有最亮的阴影。下面是一个示例,它显示了整个颜色范围(示例中有5个类)正确显示在地图本身上,但不显示在图例上 我认为问题出在以下代码中的某个地方,特别是在“根据下拉菜单中的选择计算分位数并更新图例”标题下的最后一长段代码中。我想知道在图例中添加值标签的方式是否有问题,这可能会混淆颜色的关联方式。如有任何见解,将不胜感激 下拉菜单:Map 创建正确显示分位数类范围值和配色方案中关联颜色的choropleth贴图图例?,map,d3.js,legend,colorbrewer,Map,D3.js,Legend,Colorbrewer,我是一个新手程序员,正在尝试制作一个交互式choropleth地图。在获得了关于几个问题的帮助之后,最后一个大问题是地图图例不正确。图例应该为每个分位数类别显示不同的颜色,但到目前为止,将最暗的颜色与第二大类别关联(而不是仅为最大类别),然后为最大类别重复该颜色。此外,对于大多数可用的分位数选择选项,图例中没有最亮的阴影。下面是一个示例,它显示了整个颜色范围(示例中有5个类)正确显示在地图本身上,但不显示在图例上 我认为问题出在以下代码中的某个地方,特别是在“根据下拉菜单中的选择计算分位数并更新
<div id="mapcontrols" style="position:absolute; top: 35px; left:625px;">
<div>
<p>Data to map:
<select id="NumerSelection" class="MainData" style="width:225px;">
<option value="d.OneFill" selected>Inverse (numerator set to 1)</option>
<option value="d.pop11">County Population, July 2011</option>
<option value="d.Members">Total Enrollees</option>
<option value="d.Patients">Total Patients</option>
<option value="d.MemberMonths">Member-months of Enrollment</option>
<option value="d.AvgMembers">Average Number of Enrollees</option>
<option value="d.id">County ID</option>
</select></p>
<p>Denominator:
<select id="DenomSelection" class="MainData" style="width:225px;">
<option value="d.OneFill" selected>raw rate</option>
<option value="d.pop11">County Population, July 2011</option>
<option value="d.Members">Total Enrollees</option>
<option value="d.Patients">Total Patients</option>
<option value="d.MemberMonths">Member-months of Enrollment</option>
<option value="d.AvgMembers">Average Number of Enrollees</option>
<option value="d.id">County ID</option>
</select></p>
<p>Color Scheme:
<select id="ColorSelection">
<option value="Blues" selected>Blues</option>
<option value="Greys">Greys</option>
<option value="Greens">Greens</option>
<option value="Oranges">Oranges</option>
<option value="Reds">Reds</option>
<option value="Purples">Purples</option>
<option value="YlGn">Yellow-Green</option>
<option value="YlGnBu">Yellow-Green-Blue</option>
<option value="GnBu">Green-Blue</option>
<option value="BuGn">Blue-Green</option>
<option value="PuBuGn">Purple-Blue-Green</option>
<option value="PuBu">Purple-Blue</option>
<option value="BuPu">Blue-Purple</option>
<option value="RdPu">Red-Purple</option>
<option value="PuRd">Purple-Red</option>
<option value="OrRd">Orange-Red</option>
<option value="YlOrRd">Yellow-Orange-Red</option>
<option value="YlOrBr">Yellow-Orange-Brown</option>
</select></br>
Number of quantiles:
<select id="TileSelection" class="MainData"">
<option value="3">3</option>
<option value="4">4</option>
<option value="5" Selected>5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
</select></p>
</div>
<div id="legenddiv"><p>Legend:</p></div>
</div>
根据从“颜色方案”下拉菜单中的选择,同时更新地图多边形以及图例框的颜色方案:
d3.select("select#ColorSelection")
.on("keyup", function() {d3.selectAll("svg#Mapsvg, svg#Legendsvg").attr("class", this.value)})
.on("change", function() {d3.selectAll("svg#Mapsvg, svg#Legendsvg").attr("class", this.value)});
设置要显示的值的格式:
function makenice(d) {
if(d==0){return 0;}
dec = Math.ceil(Math.log(d < 0 ? -d: d)/Math.log(10))
magnitude = Math.pow(10,3-dec)
n = Math.round(d*magnitude)/magnitude
if(dec>3){ d= numeral(n).format('0,0.[0]');}
else{ d = numeral(n).format('0.00[0000000000]');}
return d
};
根据下拉菜单中的选择计算分位数并更新图例:
d3.selectAll('select.MainData').on('change', function() {
var Nu = document.getElementById('NumerSelection')
Numer = Nu.options[Nu.selectedIndex].value;
var Nd = document.getElementById('DenomSelection')
Denom = Nd.options[Nd.selectedIndex].value;
var Qt = document.getElementById('TileSelection')
ntiles = Qt.options[Qt.selectedIndex].value;
var DataArray =(data.map(function(d, i) {return +eval(Numer) / +eval(Denom);})).sort(function(a,b){return a-b});
//set up quantiles
var quants = d3.scale.quantile()
.domain(DataArray)
.range(d3.range(0,ntiles).map(function(i) {return 'q' + i + '-' + ntiles;}))
;
var legendquant = quants.copy();
//regenerate values for legend
var legend = legendquant.quantiles();
legend.unshift(d3.min(DataArray));
legend.push(d3.max(DataArray));
legend.reverse();
//Create the legend
var delabeltext = d3.select('svg#Legendsvg').selectAll('text').remove();
var delabelboxes = d3.select('svg#Legendsvg').selectAll('rect').remove();
console.log(legend)
var legends = d3.select('svg#Legendsvg')
var legendbars = legends.selectAll('text')
.data(legend)
.enter()
.append('text')
.attr('x', 40)
.attr('y', function(d, i) {return (i*30+30)})
.text(function (d) {return d})
;
legend.pop();
legend.reverse();
if (Nu.options[Nu.selectedIndex].text != 'Inverse (numerator set to 1)') {
legend.reverse(); }
var legends = d3.select('svg#Legendsvg')
var legendbars = legends.selectAll('rect')
.data(legend)
.enter()
.append('rect')
.attr('x', 5)
.attr('y', function(d, i) {return (i*30)+25})
.attr('height',28)
.attr('width',30)
.attr('class', function (d) {return quants(d)} )
;
分位数刻度的quantiles()
方法返回每个分位数的阈值(请参阅)。引用
小于阈值数组中第一个元素分位数()[0]的值将在第一个分位数中考虑
这意味着阈值将映射到上面的相应间隔。在您的情况下,您传递的是最后一个分位数阈值,它映射到最高分位数,然后是最大值,它也映射到最高分位数
解决此问题的最简单方法可能是删除第一个元素,而不是删除图例数组的最后一个元素(
legend.pop()
)。也就是说,只需交换弹出最后一个元素的行并反转数组。Hello@meetamit,作为一名新手,我实际上刚刚超过了接受和向上投票所需的15个信誉点,所以我将回顾前面的问题,按照你说的做。谢谢是的,@Lars,这解决了问题。我真的很感谢你的帮助@用户2072931:如果您的项目可以在线公开访问,请共享。我很想在维基百科的cloropleth地图中添加这样的图例。Hello@Hugoplz,不幸的是,没有一个版本可以在网上公开访问,因为这个项目从来没有完成过,但是,正如Lars所建议的,只是在下面的代码中加上“legend.reverse();”而不是原来的“legend.pop();”上面原始问题中的“根据下拉菜单中的选择计算分位数并更新图例”对我很有用。
d3.csv('testdata.csv', function(data)
{
...
d3.selectAll('select.MainData').on('change', function() {
var Nu = document.getElementById('NumerSelection')
Numer = Nu.options[Nu.selectedIndex].value;
var Nd = document.getElementById('DenomSelection')
Denom = Nd.options[Nd.selectedIndex].value;
var Qt = document.getElementById('TileSelection')
ntiles = Qt.options[Qt.selectedIndex].value;
var DataArray =(data.map(function(d, i) {return +eval(Numer) / +eval(Denom);})).sort(function(a,b){return a-b});
//set up quantiles
var quants = d3.scale.quantile()
.domain(DataArray)
.range(d3.range(0,ntiles).map(function(i) {return 'q' + i + '-' + ntiles;}))
;
var legendquant = quants.copy();
//regenerate values for legend
var legend = legendquant.quantiles();
legend.unshift(d3.min(DataArray));
legend.push(d3.max(DataArray));
legend.reverse();
//Create the legend
var delabeltext = d3.select('svg#Legendsvg').selectAll('text').remove();
var delabelboxes = d3.select('svg#Legendsvg').selectAll('rect').remove();
console.log(legend)
var legends = d3.select('svg#Legendsvg')
var legendbars = legends.selectAll('text')
.data(legend)
.enter()
.append('text')
.attr('x', 40)
.attr('y', function(d, i) {return (i*30+30)})
.text(function (d) {return d})
;
legend.pop();
legend.reverse();
if (Nu.options[Nu.selectedIndex].text != 'Inverse (numerator set to 1)') {
legend.reverse(); }
var legends = d3.select('svg#Legendsvg')
var legendbars = legends.selectAll('rect')
.data(legend)
.enter()
.append('rect')
.attr('x', 5)
.attr('y', function(d, i) {return (i*30)+25})
.attr('height',28)
.attr('width',30)
.attr('class', function (d) {return quants(d)} )
;