D3.js 利用着色条件构建地图

D3.js 利用着色条件构建地图,d3.js,dc.js,crossfilter,D3.js,Dc.js,Crossfilter,我正在尝试构建一个choropleth,它在dc.js中并不完全是choropleth。我试图做的是根据着色条件对地图进行着色,最终这将与其他图表和过滤器进行交互。我的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 = crossf

我正在尝试构建一个choropleth,它在dc.js中并不完全是choropleth。我试图做的是根据着色条件对地图进行着色,最终这将与其他图表和过滤器进行交互。我的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),它应该返回“yes”或“no”。我不明白我和我的“团队”有什么关系

如果每个国家的
条件
值在每次数据中列出时都相同,那么从某种意义上说,数据是正确的。这很好,因为交叉过滤器在处理单个数据数组时效果最好

当然,这意味着choropleth不会对在其他图表上的涂刷做出响应,因为该值不受当前过滤的行数的影响。但它将能够过滤其他图表

是的 有几种方法可以做到这一点。一种方法是计算“是”的数量,并根据计数设置值:

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(函数(d){
返回d.condition=='no'?-1:d.condition=='yes':+1:0;
});
worldMap.valueAccessor(功能(kv){
返回千伏值<0?“否”:千伏值>0?“是”:“零”;
})
否/是极性 我们还可以分别记住计数和极性。这可能更安全,但也可能更慢。(除非你的数据很大,否则你不会注意到。)这有点复杂。有点偏好的问题

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';
})
var nozeroyesGroup=countryDimension.group().reduce(
函数(p,v){//add
if(极性和极性!=v条件)
console.warn(‘不一致’);
p、 极性=电压条件;
++p、 计数;
返回p;
},
函数(p,v){//remove

如果(p.polarity!=v.condition | | p.count不要使用
颜色计算器
;这是不推荐使用的,会破坏颜色刻度,看起来是正确的。你的意思是每个国家的
条件始终只有yes或no?还是你想使用大多数?最后,它看起来像是你的
国家维度
应该使用
country
而不是
pocc
。是的,因此每个国家都将有是或否作为其条件。因此像“SG”这样的国家将被涂成“绿色”,而“NZ”将被涂成“蓝色”,当我将鼠标悬停在每个国家上方时,工具提示应该显示
country:SG条件:Yes
,因此我假设
d.value
返回con是或否。是的,它是指国家而不是pocc。提前谢谢戈登。谢谢戈登这似乎对地图的着色起到了作用。当然,单击某些国家会相应地过滤其他图表,但单击其他图表时,它不会过滤出地图。我仔细检查了所有尺寸和颜色它们都是不同的,都是正确的。对,我在上面警告过。你希望它们如何过滤?当剩下0个yesses时,它会变成蓝色?或者灰色?也许你想把大多数yesses都涂上颜色?这就是我问的原因。几乎我有另一个图表,一个由
国家的条形图组成的行图,它的高度是
。如果我点击某个栏,说“US”,它应该几乎会留下“US”的颜色,其他所有颜色都应该是未定义区域的颜色。因此在我这边,所有“是”国家都是绿色,“否”国家都是蓝色,不包括(未定义)的国家是银色的。啊哈,现在我们正在取得进展。它将介于这两种方法之间。我明天会更新我的答案,除非你在那之前弄清楚。如果被单击的国家出现
选择
类,而其他未被单击的国家出现
取消选择的
类,也会很好,所以行图表将模拟地图上特定国家的点击事件。但一切都很好,非常感谢您的帮助
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';
})