Crossfilter 在 dc.js 上显示负数且数据集中没有负数
Crossfilter showing negative numbers on dc.js with no negative numbers in the dataset
我正在使用 CrossFilter 和 dc.js 创建 4 个不同的条形图并允许用户使用图表上的画笔功能更改数据,因此当用户更改一个图表上的画笔时其他动态变化。
除了一个有趣的问题,这一切对我来说都很有用,看起来 CrossFilter 或 dc.js 正在将负值放在图表上,但只有当图表的某些部分是 select编辑。
因此,正如您从图像中看到的那样,当我 select 图表的某个区域似乎没有值时,这在其他图表中显示为负值。
我的数据中有四个项目,日期、类型(字符串)、值(数字)和分组值(这是分组为 50 个较小值块的值)
然后我在每条数据上有 4 个维度和 4 个组,这些被提供给图表。
我的数据中从来没有任何负值,那么我的图表怎么会显示负值呢?
我是 CrossFilter 和 dc.js 的新手,所以我不确定这里显示的最佳方法或最佳代码片段,如果还有其他我应该分享的内容,请告诉我,我真的需要帮助来理解为什么我的图表中有负数。
编辑:添加代码
这是我的数据示例:
[{"Id":"1","InDate":"31/10/2015","Type":"New","Category":"cat1","Value":"1.400874145"},
{"Id":"2","InDate":"21/10/2014","Type":"Old","Category":"cat2","Value":"0"}]
我使用 CSV 文件中的 d3.csv 函数读取了它。我对 CSV 文件中的负值进行了三重检查。
以下是我设置维度的方法:
var ndx = crossfilter(data);
var parseDate = d3.time.format("%d/%m/%Y").parse;
data.forEach(function(d) {
d.date = parseDate(d.InDate);
d.valueGrouped = createValueGrouping(parseFloat(d.Value));
});
var dateDim = ndx.dimension(function(d) {return d.date;});
var typeDim = ndx.dimension(function(d) {return d.Type;});
var valueGroupDim = ndx.dimension(function(d) {return d.valueGrouped;});
var categoryDim = ndx.dimension(function(d) {return d.Category;});
这是创建 valueGrouped 属性的函数:
function createValueGrouping(value){
return 50 * Math.round(value/50);
}
最后是我设置群组的方法:
var timelineGroup = dateDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
var typeGroup = typeDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
var valueGrouped = valueGroupDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
var categoryGroup = categoryDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
编辑 2:添加 JSFiddle
Fiddle - JSFiddle
看起来这些是无穷小的负数,这可能表示由于浮点数没有完全抵消而引起的故障。
当您对数量级差异较大的浮点数进行相加时,运算不一定是关联或分配的,这意味着如果您以不同的顺序相加,您将得到不同的结果。
https://en.m.wikipedia.org/wiki/Floating_point#Accuracy_problems
另外,crossfilter减法的顺序和加法的顺序不同,所以经常出现这种问题。
我建议创建一个假组来包装您的数据,并在它们非常接近时将值设置为零:
function snap_to_zero(source_group) {
return {
all:function () {
return source_group.all().map(function(d) {
return {key: d.key,
value: (Math.abs(d.value)<1e-6) ? 0 : d.value};
});
}
};
}
在您发现问题的任何地方用这个函数包装您的原始组:
chart.group(snap_to_zero(valueGrouped))
我正在使用 CrossFilter 和 dc.js 创建 4 个不同的条形图并允许用户使用图表上的画笔功能更改数据,因此当用户更改一个图表上的画笔时其他动态变化。
除了一个有趣的问题,这一切对我来说都很有用,看起来 CrossFilter 或 dc.js 正在将负值放在图表上,但只有当图表的某些部分是 select编辑。
因此,正如您从图像中看到的那样,当我 select 图表的某个区域似乎没有值时,这在其他图表中显示为负值。
我的数据中有四个项目,日期、类型(字符串)、值(数字)和分组值(这是分组为 50 个较小值块的值)
然后我在每条数据上有 4 个维度和 4 个组,这些被提供给图表。
我的数据中从来没有任何负值,那么我的图表怎么会显示负值呢?
我是 CrossFilter 和 dc.js 的新手,所以我不确定这里显示的最佳方法或最佳代码片段,如果还有其他我应该分享的内容,请告诉我,我真的需要帮助来理解为什么我的图表中有负数。
编辑:添加代码
这是我的数据示例:
[{"Id":"1","InDate":"31/10/2015","Type":"New","Category":"cat1","Value":"1.400874145"}, {"Id":"2","InDate":"21/10/2014","Type":"Old","Category":"cat2","Value":"0"}]
我使用 CSV 文件中的 d3.csv 函数读取了它。我对 CSV 文件中的负值进行了三重检查。
以下是我设置维度的方法:
var ndx = crossfilter(data);
var parseDate = d3.time.format("%d/%m/%Y").parse;
data.forEach(function(d) {
d.date = parseDate(d.InDate);
d.valueGrouped = createValueGrouping(parseFloat(d.Value));
});
var dateDim = ndx.dimension(function(d) {return d.date;});
var typeDim = ndx.dimension(function(d) {return d.Type;});
var valueGroupDim = ndx.dimension(function(d) {return d.valueGrouped;});
var categoryDim = ndx.dimension(function(d) {return d.Category;});
这是创建 valueGrouped 属性的函数:
function createValueGrouping(value){
return 50 * Math.round(value/50);
}
最后是我设置群组的方法:
var timelineGroup = dateDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
var typeGroup = typeDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
var valueGrouped = valueGroupDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
var categoryGroup = categoryDim.group().reduceSum(function(d) {return parseFloat(d.Value);});
编辑 2:添加 JSFiddle
Fiddle - JSFiddle
看起来这些是无穷小的负数,这可能表示由于浮点数没有完全抵消而引起的故障。
当您对数量级差异较大的浮点数进行相加时,运算不一定是关联或分配的,这意味着如果您以不同的顺序相加,您将得到不同的结果。
https://en.m.wikipedia.org/wiki/Floating_point#Accuracy_problems
另外,crossfilter减法的顺序和加法的顺序不同,所以经常出现这种问题。
我建议创建一个假组来包装您的数据,并在它们非常接近时将值设置为零:
function snap_to_zero(source_group) {
return {
all:function () {
return source_group.all().map(function(d) {
return {key: d.key,
value: (Math.abs(d.value)<1e-6) ? 0 : d.value};
});
}
};
}
在您发现问题的任何地方用这个函数包装您的原始组:
chart.group(snap_to_zero(valueGrouped))