我正在努力建立一个在dc.js中并不完全是一个等值的合唱。我要做的是根据着色条件为地图着色,最终这也将与其他图表和过滤器进行交互。我的csv看起来像这样:
country,id,condition,value
AU,1,yes,19
US,2,no,23
US,2,no,30
US,2,no,4
IN,3,yes,14
SG,4,yes,2
NZ,5,no,6
NZ,5,no,20
这是我到目前为止的方法,产生了发生次数。
var ndx = crossfilter(data)
var countryDimension = ndx.dimension(function (d){
return d.country
});
var colors = d3.scale.ordinal().domain(['yes','no']).range(["green","blue"])
worldMap.width(mapWidth)
.height(mapHeight)
.dimension(countryDimension)
.group(countryDimension.group())
.projection(project)
.colors(colors)
.colorCalculator(function(d){
return d ? worldMap.colors()(d) : '#d8d8d8';
})
.overlayGeoJson(geoJson.features, "id", function(d){
return d.id;
})
.title(function(d){
return 'Country: ' + d.key + '\nCondition: ' + d.value;
});
我对这个令人惊叹的d3和dc.js世界都很陌生。虽然我一直在阅读文档和论坛,但我无法弄清楚我是如何制作它以便绘制地图的,以及具有条件的国家'是'是绿色和有条件的国家没有'是蓝色的。所以,如果我做console.log(d.value)它应该返回“是”'或者没有'。我不知道我和我的小组有什么关系。
答案 0 :(得分:1)
如果每个国家/地区在数据中列出condition
时都具有相同的值,那么在某种意义上,数据为denormalized。这很好,因为crossfilter最适合单个数据阵列。
当然,这意味着等值线不会响应其他图表上的刷牙,因为该值不受当前过滤的行数的影响。但它可以过滤其他图表。
有几种方法可以做到这一点。一种方法是计算yes的数量,并根据计数设置值:
var yesnoGroup = countryDimension.group().reduceSum(function(d) {
return d.condition === 'yes' ? 1 : 0;
});
worldMap.valueAccessor(function(kv) {
return kv.value ? 'yes' : 'no';
})
然而,这可能会导致各国在被其他图表过滤掉时变成蓝色。所以你也可以使用“抓住第一个值并坚持下去”这样的策略:
var yesnoGroup = countryDimension.group().reduce(
function(p, v) { // add
return v.condition;
},
function(p, v) { // remove
return p; // ignore remove event
},
function() { // initialize
return null; // no value
});
使用crossfilter有点丑陋和奇怪的方式,但这只是因为crossfilter期望数据对减少的值产生一些影响,而不是在这里。
根据下面的对话,我了解到你实际上在寻找三种状态:不,零和是。 (这比上面的解决方案更有意义,但我会留给后人的。)这里有两种完全不同的方法来解决no / zero / yes问题。
这两种解决方案都使用以下三向色标:
var colors = d3.scale.ordinal().domain(['no', 'zero', 'yes']).range(["blue", "grey", "green"])
这很聪明,很简单:我们只将每个号码计为-1
,将每个号码计为+1
。如果总和为零,我们将画灰色。这里唯一需要注意的是,如果数据中存在矛盾,则可能会出现假零。但这可能比假的没有或是(?)
var nozeroyesGroup = countryDimension.group().reduceSum(function(d) {
return d.condition === 'no' ? -1 : d.condition === 'yes' : +1 : 0;
});
worldMap.valueAccessor(function(kv) {
return kv.value < 0 ? 'no' : kv.value > 0 ? 'yes' : 'zero';
})
我们还可以分别记住计数和极性。这可能更安全但也可能更慢。 (除非你的数据很大,否则你不会注意到。)这有点复杂。这是一种偏好。
var nozeroyesGroup = countryDimension.group().reduce(
function(p, v) { // add
if(p.polarity && p.polarity != v.condition)
console.warn('inconsistent');
p.polarity = v.condition;
++p.count;
return p;
},
function(p, v) { // remove
if(p.polarity != v.condition || p.count <= 0)
console.warn('inconsistent');
--p.count;
return p;
},
function() { // initialize
return {count: 0, polarity: null}; // no value
});
worldMap.valueAccessor(function(kv) {
return kv.value.count ? kv.value.polarity : 'zero';
})