从d3plus框和胡须图绘制中抑制极端异常值

时间:2017-11-10 17:45:31

标签: javascript d3.js boxplot outliers d3plus

我正在尝试在d3plus上创建带有胡须的盒子图,以比较我的数据库中“this”提供者和“所有”提供者之间的度量。我已经在预处理阶段计算了非常大的数组的5统计摘要,我将它们传递给data变量。如果您运行附加的代码段(从d3plus website example修改),您可以看到代码和图表的样子。然而,实际上,“All”类别中存在一些极端异常值,我的代码作为注释行:663373.22表示“max”(表示“All”)和-18427.39表示“min”(同样,“All” “)。

我看到mute method可以用于.y,但我不确定如何使用函数。

是否有一种相当直接的方法可以“抑制”这些极端异常值的绘制(如果允许,可以将箱形图折叠成扁平线),或任何极端异常值,例如高于(或低于)某些极端异常值IQR的倍数?

<script src="//d3plus.org/js/d3.js"></script>
<script src="//d3plus.org/js/d3plus.js"></script>

<div id="viz"></div>

<script>
  var data = [
    {"provider": "This", "name":"min", "value": -1055.79},
    {"provider": "This", "name":"q1", "value": -172.819},
    {"provider": "This", "name":"med", "value": -46.795},
    {"provider": "This", "name":"q3", "value": 8.378},
    {"provider": "This", "name":"max", "value": 1033.15},
    {"provider": "All", "name":"min", "value": -1000},
    {"provider": "All", "name":"q1", "value": -111.60999999999999},
    {"provider": "All", "name":"med", "value": -13.92},
    {"provider": "All", "name":"q3", "value": 124.22},
    {"provider": "All", "name":"max", "value": 1000}
  ]
  //663373.22, -18427.39
  var visualization = d3plus.viz()
    .container("#viz")
    .data(data)
    .type("box")
    .id("name")
    .x("provider")
    .y("value")
    .ui([{ 
        "label": "Visualization Type",
        "method": "type", 
        "value": ["scatter","box"]
      }])
    .draw()
</script>

1 个答案:

答案 0 :(得分:2)

根据我对文档的理解,mute用作对象键,其中值可以是字符串,函数或数组。因此,如果您要将名称为q1的所有数据点静音,您可以执行.y({value:'value',mute:'q1'})

至于解决方案,您需要一个确定异常值的函数。我找到并编辑了一个函数来返回可接受的值范围(IQR * multiple),您可以根据需要修改multiple变量。然后使用简单函数isOutlier来检查传入的值是否在范围之外。

<script src="//d3plus.org/js/d3.js"></script>
<script src="//d3plus.org/js/d3plus.js"></script>

<div id="viz"></div>

<script>
  var data = [
    {"provider": "This", "name":"min", "value": -1055.79},
    {"provider": "This", "name":"q1", "value": -172.819},
    {"provider": "This", "name":"med", "value": -46.795},
    {"provider": "This", "name":"q3", "value": 8.378},
    {"provider": "This", "name":"max", "value": 1033.15},
    {"provider": "All", "name":"min", "value": -1000},
    {"provider": "All", "name":"q1", "value": -111.60999999999999},
    {"provider": "All", "name":"med", "value": -13.92},
    {"provider": "All", "name":"q3", "value": 124.22},
    {"provider": "All", "name":"max", "value": 1000}
  ]
 
  var outlierRange = outlierRange(data.map(d=>d.value))
  var isOutlier = val =>  (val < outlierRange[0] || val > outlierRange[1])

  //663373.22, -18427.39
  var visualization = d3plus.viz()
    .container("#viz")
    .data(data)
    .type("box")
    .id("name")
    .x("provider")
    .y({value:'value', mute: isOutlier })
    .ui([{ 
        "label": "Visualization Type",
        "method": "type", 
        "value": ["scatter","box"]
      }])
    .draw()
  
function outlierRange(someArray) {

  if(someArray.length < 4)
return someArray;

  let values, q1, q3, iqr, maxValue, minValue, multiple = 0.5;

  values = someArray.slice().sort( (a, b) => a - b);//copy array fast and sort

  if((values.length / 4) % 1 === 0){//find quartiles
q1 = 1/2 * (values[(values.length / 4)] + values[(values.length / 4) + 1]);
q3 = 1/2 * (values[(values.length * (3 / 4))] + values[(values.length * (3 / 4)) + 1]);
  } else {
q1 = values[Math.floor(values.length / 4 + 1)];
q3 = values[Math.ceil(values.length * (3 / 4) + 1)];
  }

  iqr = q3 - q1;
  maxValue = q3 + iqr * multiple;
  minValue = q1 - iqr * multiple;

  return [minValue, maxValue]
}




</script>