对于向右倾斜的数据,请使用正确的色标

时间:2018-03-29 16:02:43

标签: javascript d3.js colors data-visualization

我的数据域为[0,100],但它们并不统一,它们向右倾斜,即大多数数据的值介于80和100之间。

我想用这些数据进行可视化,并使用颜色来区分它们(例如:热图,地图,......)。

使用什么样的色标?

我尝试了线性刻度,功率刻度和分位数刻度。 最好的一个看起来像分位数,但仍然存在问题:

  1. 我想更好地区分最后一个值的颜色(右边的值),它们看起来都是黑色的,是否可能?
  2. 在这个例子中我使用了灰度,如果我想使用 Viridis Magma 比例?
  3. enter image description here

    这是我的代码。

    function sortNumber(a, b) {
      return a - b;
    }
    
    var data = [90, 95, 50, 1, 99, 89.1, 87, 94, 95, 99, 99.5, 94.3, 96, 97, 85, 74, 66, 92, 68, 91, 93, 87, 79, 86, 89, 93.5, 97, 98];
    data.sort(sortNumber); // [1, 50, 66, 68, 74, 79, 85, 86, 87, 87, 89, 89.1, 90, 91, 92, 93, 93.5, 94, 94.3, 95, 95, 96, 97, 97, 98, 99, 99, 99.5]
    console.log(data);
    
    var colMin = '#ffffff';
    var colMax = '#000000';
    
    // LINEAR SCALE
    var scaleLinear = d3.scaleLinear()
      .domain([0, 100])
      .range([colMin, colMax]);
    
    var div = d3.select("#lin").selectAll(null)
      .data(data)
      .enter()
      .append("div")
      .attr("class", "dive")
      .style("background-color", d => scaleLinear(d));
    
    
    // POWER SCALE
    var scalePow = d3.scalePow()
      .exponent(10)
      .domain([0, 100])
      .range([colMin, colMax]);
    
    var div = d3.select("#pow").selectAll(null)
      .data(data)
      .enter()
      .append("div")
      .attr("class", "dive")
      .style("background-color", d => scalePow(d));
    
    
    // QUANTILE SCALE (using https://meyerweb.com/eric/tools/color-blend/#:::hex to find intermediate colors)
    var scaleQuantile = d3.scaleQuantile()
      .domain(data)
      .range([colMin, "#E8E8E8", "#D1D1D1", "#B9B9B9", "#A2A2A2", "#8B8B8B", "#747474", "#5D5D5D", "#464646", "#2E2E2E", "#171717", colMax]);
    
    var div = d3.select("#qua").selectAll(null)
      .data(data)
      .enter()
      .append("div")
      .attr("class", "dive")
      .style("background-color", d => scaleQuantile(d));
    .dive {
      width: 20px;
      height: 20px;
      display: inline-block;
      margin: 4px;
      border: 0.5px black solid;
    }
    <html lang="en">
    
    <head>
       <meta charset="utf-8">
       <title>color scheme</title>
       <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
       <script src="//d3js.org/d3-scale-chromatic.v0.3.min.js"></script> <!-- for scale color -->
       <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> <!-- for scale color -->
    
       <link rel="stylesheet" type="text/css" href="./style.css" media="screen"/>
    </head>
    
    <body>
       <div id="lin">
       	<p>Scale linear</p>
       </div><br>
    
       <div id="pow">
       	<p>Scale power</p>
       </div><br>
    
       <div id="qua">
       	<p>Scale quantile</p>
       </div>
    
       <script src="./script.js"></script>
    </body>
    
    </html>

    结果如下:

    enter image description here

3 个答案:

答案 0 :(得分:5)

  

我想更好地区分最后值的颜色   (右边的值),它们看起来都是黑色的,是否可能?

正如Klaujesi所说,制作自己的色标可能是你最好的选择。我会参考Klaujesi的答案来编写关于创建自己的配色方案的指导。

正如您所确定的那样,您有许多具有相似价值的数据点,您已经尝试过的量表已经反映出来。就个人而言,我会考虑仍然让你的规模反映这个事实,而不是太努力地用更具吸引力的规模隐藏它。我建议考虑一下您的数据意味着什么,并创建一个比例来反映这一点。例如,可能90到100范围内的所有数据点应该具有比80到100范围内的数据点更相似的颜色。或者你真的应该让所有的颜色看起来都一样,因为所有的数据都是相同的。

  

在这个例子中,我使用了灰度,如果我想使用   Viridis或Magma规模?

感谢您在组织一个好榜样方面所做的工作,添加其中一种配色方案应该不会太困难。这是一个线性刻度的例子。

添加到script.js的底部:

// VIRIDIS
var colorScale = d3.scaleLinear()
  .domain([0, 100])
  .range([0, 1]);

var div = d3.select("#vir").selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .attr("class", "dive")
  .style("background-color", d => d3.interpolateViridis(colorScale(d)));

<body>的{​​{1}}内添加:

index.html

答案 1 :(得分:1)

由于您的数据偏向右侧,这是我的建议:

在此示例中使用sequential scale interpolateViridis

var scale = d3.scaleSequential(d3.interpolateViridis);

只需将数据的索引与插值器一起使用:

.style("background-color", function(_, i) {
    return scale(i / (data.length - 1))
});

或者,当你正在使用viridis 逆转时:

.style("background-color", function(_, i) {
    return scale(1 - (i / (data.length - 1)))
});

原因在于,使用顺序缩放,只有数据数组中数据的索引很重要,而不是数据本身。因此,请确保数据数组已排序。

以下是演示:

&#13;
&#13;
var data = [90, 95, 50, 1, 99, 89.1, 87, 94, 95, 99, 99.5, 94.3, 96, 97, 85, 74, 66, 92, 68, 91, 93, 87, 79, 86, 89, 93.5, 97, 98];
data.sort();
var scale = d3.scaleSequential(d3.interpolateViridis);
var div = d3.select("#myDiv").selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .attr("class", "div")
  .style("background-color", function(_, i) {
    return scale(1 - (i / (data.length - 1)))
  });
  
var divValue = d3.select("#myDivValue").selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .attr("class", "div2")
  .html(Number)
&#13;
.div {
  width: 14px;
  height: 14px;
  display: inline-block;
  margin: 2px;
  border: 0.5px black solid;
}

.div2 {
  width: 14px;
  height: 14px;
  display: inline-block;
  margin: 2px;
  font-size: 10px;
  border: 0.5px white solid;
}
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="myDiv">
  <p>Sequential scale with Viridis</p>
</div>
<div id="myDivValue"></div>
&#13;
&#13;
&#13;

相同的代码,使用interpolateMagma

&#13;
&#13;
var data = [90, 95, 50, 1, 99, 89.1, 87, 94, 95, 99, 99.5, 94.3, 96, 97, 85, 74, 66, 92, 68, 91, 93, 87, 79, 86, 89, 93.5, 97, 98];
data.sort();
var scale = d3.scaleSequential(d3.interpolateMagma);
var div = d3.select("#myDiv").selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .attr("class", "div")
  .style("background-color", function(_, i) {
    return scale(1 - (i / (data.length - 1)))
  });
var divValue = d3.select("#myDivValue").selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .attr("class", "div2")
  .html(Number);
&#13;
.div {
  width: 14px;
  height: 14px;
  display: inline-block;
  margin: 2px;
  border: 0.5px black solid;
}

.div2 {
  width: 14px;
  height: 14px;
  display: inline-block;
  margin: 2px;
  font-size: 10px;
  border: 0.5px white solid;
}
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="myDiv">
  <p>Sequential scale with Magma</p>
</div>
<div id="myDivValue"></div>
&#13;
&#13;
&#13;

PS:我在这里使用D3 v5。如果您正在使用v4,则可能需要引用必要的微库。

答案 2 :(得分:0)

  

使用什么样的色标?

不正确的色标。一切都取决于您想要展示,隐藏,销售,您的客户,客户,用户,公众.-

另一方面,你有D3作为工具来显示你需要的东西.-

您可以使用自定义比例,如下所示:

  // --------------------- Custom  SCALE
var custom = d3.scaleLinear()
  .domain([0,       50,       90,        95,       100])
  .range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);

var div = d3.select("#custom").selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .attr("class", "dive")
  .style("background-color", d => custom(d));

这给了你:

enter image description here

还有其他人。

enter image description here

我将你的Plunker分叉以扩展它:HERE

我认为您错过了一个重要的观点:您正在丢弃信息。 显示这一点的正确方法是留下空白空间以缺少数据,例如任何颜色标度都可以。像这样:

enter image description here

从你的形象

enter image description here

On&#34; Scale Quantile&#34; &#34; Scale Power&#34;,&#34; value 1&#34;具有与&#34;值50和#34;相同的颜色。即使你用他的价值标记每个方框,也很难注意到.-

希望这个帮助