【问题标题】:dc.js average value over the summed field总和字段上的 dc.js 平均值
【发布时间】:2020-07-08 11:36:36
【问题描述】:

我有以下数据数组:

身份证号码 ---- ------ -------- 1 G 1 1 G 2 1 楼 3

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

ID 姓名 Number_sum ---- ------ ------------ 1 G 3 1 楼 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>

【问题讨论】:

  • 您需要展示您的代码,因为甚至不清楚您使用的是什么库。我想我认为这是一个交叉过滤问题,因为您引用了 dc.js,但我无法从您的问题文本中弄清楚这一点。此外,您没有显示您如何错误地计算平均值。我也不知道什么是预和。
  • 我已经删除了一些模糊的标签,这些标签经常让仇恨者近距离投票,并添加了 [crossfilter]。如果这是 [javascript] 问题而不是 [crossfilter] 问题,请随时将它们改回来。
  • @Gordon 我在我使用的库中添加了代码。在此示例中,给出了单个“A”值的平均值的简单计算。
  • 感谢您添加代码,这很有帮助。还有几件事我不明白。您想显示每个名称的平均值还是整体平均值?据我所知,您的表格显示了每个名称的 sum,而不是任何 average
  • 您的代码按 ID 对行进行分类,并确定平均值为 2.0(3 行,共 6 行),看起来是正确的。如果将维度更改为名称,它会为第一个 bin(G,2 行,总共 3)产生 1.5 的平均值,这也是正确的。我想我不明白你在做什么。

标签: d3.js dc.js crossfilter


【解决方案1】:

为了计算平均值,考虑到“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>

【讨论】:

  • 很高兴你知道了!我认为这与我的回答具有相同的效果,因为唯一键的数量将是该字段上一个维度中的 bin 数量。
  • 我想不同的是,这将计算每个 ID 的名称的平均值,而我的计算所有名称的平均值。
  • @Gordon 好的。在我的决定中,考虑到唯一“名称”值的数量,可以在 id 的上下文中输入平均值。因此,将来我可能会将此代码用于图形,其中“名称”字段不是最大数据粒度。结果,无论输入中有多少详细数据。您始终可以根据感兴趣的详细程度计算平均值。
【解决方案2】:

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

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)

【讨论】:

  • 这就是我修复标签的原因。不过感谢您的回答!
【解决方案3】:

我不确定我是否完全理解,但如果您想按名称分组,求和,然后取所有组的平均值,您可以将您的维度放在名称上并使用常规reduceSum

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

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

                .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>

【讨论】:

    猜你喜欢
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多