dc.js 求和字段的平均值

dc.js average value over the summed field

我有以下数据数组:

  ID   Name   Number  
 ---- ------ -------- 
   1   G           1  
   1   G           2  
   1   F           3  

我想做下面的转换来计算平均值,但是我不知道怎么做。

  ID   Name   Number_sum  
 ---- ------ ------------ 
   1   G               3  
   1   F               3  

求和后求平均值

  ID   Number_avg  
 ---- ------------ 
   1            3  

如果不预求和,则平均值计算错误:

  ID   Number_avg  
 ---- ------------ 
   1            2  

我想计算每个 ID 的平均值,但偶数字段“姓名”。

接下来,我打算为每个ID建立一个图表。我有一个道路标识符 - 1。这条路由 2 部分组成:G 和 F。此外,G 部分又分为 2 个小部分,每个部分 1 公里和 2 公里。

如果我们考虑通常的平均值,那么我们会得到该值的最大部分(道路的一个子部分)的平均值。但是我想根据路段的平均值进行计算

<!DOCTYPE html>
<html lang="en">
<head>
    <title>dc.js</title>
    <meta charset="UTF-8">
    
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/d3.js"></script>
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/crossfilter.js"></script>
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/dc.js"></script>


    
</head>
<body>
<div id ="test"></div>

<script type="text/javascript">
//dc.js
 var inlineND = new dc.NumberDisplay("#test");
 
//data
var array1 = [
            {"ID": 1, "Name": "G", "Number": 1},
            {"ID": 1, "Name": "G", "Number": 2},
            {"ID": 1, "Name": "F", "Number": 3}
            ];

var make_calc = function() {
            var ndx                 = crossfilter(array1), //
            Dimension               = ndx.dimension(function(d) {return d.ID;}),
            DimensionGroup          = Dimension.group().reduce(reduceAdd, reduceRemove, reduceInitial);           
            
            function reduceAdd(p, v) {
            ++p.count;
            p.total += v.Number;
            return p;
            }

            function reduceRemove(p, v) {
            --p.count;
            p.total -= v.Number;
            return p;
            }

            function reduceInitial() {
            return {count: 0, total: 0};
            }
            
            inlineND
                .group(DimensionGroup)
                .valueAccessor(function(p) { return p.value.count > 0 ? p.value.total / p.value.count : 0; });
                
            dc.renderAll();
            //console.log(DimensionGroup);
};

make_calc();

</script>
</body>
</html>

我不确定,但你在找这样的东西吗?

const arr = [
  {id: 1, name: 'G', number: 1},
  {id: 2, name: 'G', number: 2},
  {id: 3, name: 'F', number: 3}
]

const res = arr.reduce((acc, e) => {
  const idx = acc.findIndex(x => x.name === e.name)
  if (idx !== -1) {
    acc[idx].number += e.number
  } else {
    acc.push(e)
  }
  return acc
}, [])

console.log(res)

我不知道我是否完全理解,但是如果你想按名称分组,求和,然后取所有组的平均值,你可以将你的维度放在名称上并使用正则 reduceSum:

            var ndx                 = crossfilter(array1), //
            Dimension               = ndx.dimension(function(d) {return d.Name;}),
            DimensionGroup          = Dimension.group().reduceSum(d => d.Number);

然后传递一个“fake groupAll”,其中returns组中的所有行到数字显示,并在值访问器中计算平均值:

                .group({value: () => DimensionGroup.all()})
                .valueAccessor(a => a.length === 0 ? 0 : d3.sum(a, ({value}) => value) / a.length);

<!DOCTYPE html>
<html lang="en">
<head>
    <title>dc.js</title>
    <meta charset="UTF-8">
    
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/d3.js"></script>
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/crossfilter.js"></script>
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/dc.js"></script>


    
</head>
<body>
<div id ="test"></div>

<script type="text/javascript">
//dc.js
 var inlineND = new dc.NumberDisplay("#test");
 
//data
var array1 = [
            {"ID": 1, "Name": "G", "Number": 1},
            {"ID": 1, "Name": "G", "Number": 2},
            {"ID": 1, "Name": "F", "Number": 3}
            ];

var make_calc = function() {
            var ndx                 = crossfilter(array1), //
            Dimension               = ndx.dimension(function(d) {return d.Name;}),
            DimensionGroup          = Dimension.group().reduceSum(d => d.Number);

            
            inlineND
                .group({value: () => DimensionGroup.all()})
                .valueAccessor(a => a.length === 0 ? 0 : d3.sum(a, ({value}) => value) / a.length);
                
            dc.renderAll();
            //console.log(DimensionGroup);
};

make_calc();

</script>
</body>
</html>

为了计算平均值,考虑到“Name”字段,需要考虑这个字段在reduce函数中的唯一出现。结果,在计算平均值时,将值的总和除以“名称”字段中唯一值的数量

<!DOCTYPE html>
<html lang="en">
<head>
    <title>dc.js</title>
    <meta charset="UTF-8">
    
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/d3.js"></script>
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/crossfilter.js"></script>
    <script type="text/javascript" src="https://dc-js.github.io/dc.js/js/dc.js"></script>

</head>
<body>
<div id ="test"></div>

<script type="text/javascript">
//dc.js
 var inlineND = new dc.NumberDisplay("#test");
 
//data
var array1 = [
            {"ID": 1, "Name": "G", "Number": 1},
            {"ID": 1, "Name": "G", "Number": 2},
            {"ID": 1, "Name": "F", "Number": 3}
            ];

var make_calc = function() {
            var ndx                 = crossfilter(array1), //
            Dimension               = ndx.dimension(function(d) {return d.ID;}),
            DimensionGroup          = Dimension.group().reduce(reduceAdd, reduceRemove, reduceInitial);           
            
                       
            function reduceAdd(p, v) {
            ++p.count;
            p.total += v.Number;
                if(v.Name in p.Names){
                    p.Names[v.Name] += 1
                }
                else{
                    p.Names[v.Name] = 1;
                    p.Name_count++;
                };
            return p;
            }

            function reduceRemove(p, v) {
            --p.count;
            p.total -= v.Number;
                p.Names[v.Name]--;
                if(p.Names[v.Name] === 0){
                    delete p.Names[v.Name];
                    p.Name_count--;
                };
            return p;
            }

            function reduceInitial() {
            return {count: 0, total: 0, Name_count: 0, Names: {}};
            }
            
            inlineND
                .group(DimensionGroup)
                .valueAccessor(function(p) { return p.value.Name_count > 0 ? p.value.total / p.value.Name_count : 0; });
                
            dc.renderAll();
            //console.log(DimensionGroup);
};

make_calc();

</script>
</body>
</html>