2015-03-24 1 views
3

Я использую CrossFilter вместе с dc.js для создания 4 различных гистограмм и позволяет пользователю изменять данные с помощью функции кисти на диаграммах, поэтому, когда пользователь меняет кисть на одну диаграмму, другие динамически меняются.Crossfilter показывает отрицательные числа на dc.js без отрицательных чисел в наборе данных

Это все работает для меня в минутном баре одной интересной проблемой, похоже, что CrossFilter или dc.js ставят отрицательные значения на графиках, но только при выборе определенных разделов графика.

Как вы можете видеть из изображения, когда я выбираю область диаграммы, которая, как представляется, не имеет значений, показывает отрицательные значения в других диаграммах.

enter image description here

У меня есть четыре детали в моих данных, дате, типа (строка), значение (число) и сгруппированное значение (это значение сгруппировано на более мелкие куски значений 50)

И затем у меня есть 4 измерения для каждой части данных и 4 группы, и они поставляются в чарты.

В моих данных никогда не было отрицательных значений, так как мои диаграммы могут показывать отрицательные значения?

Я новичок в CrossFilter и dc.js, поэтому я не уверен в лучшем подходе или лучших фрагментах кода, чтобы показать здесь, если есть что-то еще, что я должен поделиться, пожалуйста, дайте мне знать, мне действительно нужна помощь пытаясь понять, почему на моих графиках есть отрицательные числа.

РЕДАКТИРОВАТЬ: Добавление кода

Ниже приведен пример моих данных:

[{ "Идентификатор": "1", "InDate": "31/10/2015", «Type»: «New», «Category»: «cat1», «Value»: «1.400874145»}, {«Id»: «2», «InDate»: «21/10/2014», «Type» : «Старые», «Категория»: «cat2», «Значение»: «0»}]

Я прочитал его, используя функцию d3.csv из файла CSV. Я проверил triple для отрицательных значений в 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);}); 

EDIT 2: Добавление JSFiddle

Fiddle - JSFiddle

+2

У вас, вероятно, есть ошибка в коде группировки Crossfilter, но вам нужно поделиться своим кодом, чтобы мы могли вам помочь. –

+0

@ EthanJewett - спасибо, я добавил свой код, показывающий фрагмент данных, как я настраивал размеры, а затем группы, затем я использую эти измерения и группы самым основным способом с помощью dc.js, но если вам нужно см. код диаграммы, дайте мне знать, и я добавлю его. –

+0

Добавлена ​​скрипка, показывающая проблему –

ответ

4

Похоже, что это бесконечно малые отрицательные числа, которые, вероятно, указывают на сбой, вызванный номерами с плавающей запятой, которые отлично не отменяются.

Когда вы добавляете числа с плавающей запятой с сильно различающейся величиной, операции не обязательно являются ассоциативными или дистрибутивными, а это означает, что если вы добавите числа в другом порядке, вы получите разные результаты.

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)) 
+0

Работал отлично, спасибо за предоставление вашего опыта. –

+1

Рад, что я мог помочь, и спасибо за скрипку. – Gordon

+0

Большое спасибо, Гордон – IgorShch