Для NVD3 lineChart Удалить отсутствующие значения (чтобы иметь возможность интерполировать)

Я использую NVD3 для визуализации данных об экономическом неравенстве. Диаграмма для США находится здесь: http://www.chartbookofeconomicinequality.com/inequality-by-country/USA/

Это две диаграммы lineCharts, расположенные друг над другом. Проблема в том, что у меня довольно много пропущенных значений, и это вызывает две проблемы:

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

chart = nv.models.lineChart()
            .x(function(d) { return d[0] })
            .y(function(d) { return d[1]== 0 ? null : d[1]; }) 

Но все же, если вы наведете курсор на ось x, вы увидите, что недостающие значения отображаются во всплывающей подсказке при наведении курсора мыши. Могу ли я полностью избавиться от них? Возможно использование удаления в NVD3?

Вторая проблема напрямую связана с этим. Теперь линия соединяет значения одной и той же серии, только если между ними нет пропущенных значений. Значит, в строках много пробелов. Можно ли соединить точки одной серии, даже если между ними пропущены значения?

Спасибо за помощь!


person user2656065    schedule 18.01.2014    source источник
comment
Вы можете использовать .defined() так: .defined(function(d) { return d[1] != null }). Не уверен, что это даст вам именно то, что вы хотите, но попробовать стоит.   -  person Lars Kotthoff    schedule 18.01.2014
comment
@LarsKotthoff Спасибо за ответ! Это было полезно, и я сделал еще один шаг, но я еще не там. Чтобы сделать этот поток более информативным и прояснить, что я пытаюсь сделать, я построил небольшой пример на скрипте JS. Вот он: jsfiddle.net/xammamax/8Kk8v В одном из случаев есть некоторые отсутствующие значения серии. Что я хотел бы сделать, так это соединить два не пропущенных значения до и после отсутствующих значений. Таким образом, в конце все значения отображаются маркерами, а все значения ряда визуально связаны.   -  person user2656065    schedule 27.01.2014
comment
Как this, где все отсутствующие значения удалены?   -  person Lars Kotthoff    schedule 27.01.2014
comment
Большое спасибо! Это именно то, что я хочу. Но, к сожалению, это решение только тогда, когда данные представлены в формате json. Есть ли способ добиться того же, когда я читаю данные из файла csv? Что мне делать, если строка относится к определенному году, когда есть данные для некоторых, но не для всех серий? (Я бы использовал jsfiddle, если бы знал, как включить туда файл csv.)   -  person user2656065    schedule 27.01.2014
comment
Похоже, вам нужно преобразовать его в структуру, подобную JSON, которую вы можете фильтровать.   -  person Lars Kotthoff    schedule 27.01.2014
comment
Спасибо, что ответили мне @LarsKotthoff! Поскольку это другая проблема, чем решенная здесь, я задал этот новый вопрос, связанный с данными csv, здесь: stackoverflow.com/questions/21402813/   -  person user2656065    schedule 28.01.2014


Ответы (1)


Как показал Ларс, заставить график выглядеть так, как вы хотите, нужно всего лишь удалить недостающие значения из ваших массивов данных.

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

Когда у вас есть полный массив данных в виде массива объектов серии, каждый из которых имеет массив значений, этот код должен работать:

//to remove the missing values, so that the graph
//will just connect the valid points,
//filter each data array:
data.forEach(function(series) {
    series.values = series.values.filter(
        function(d){return d.y||(d.y === 0);}
    );
    //the filter function returns true if the
    //data has a valid y value 
    //(either a "true" value or the number zero,
    // but not null or NaN)

});

Обновленная скрипка здесь: http://jsfiddle.net/xammamax/8Kk8v/

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

var chartdata = [];//initialize as empty array

d3.csv("top_1_L-shaped.csv", function(error, csv) {

    if (error)
        return console.log("there was an error loading the csv: " + error);

    var columndata = ["Germany", "Switzerland", "Portugal", 
                      "Japan", "Italy", "Spain", "France", 
                      "Finland", "Sweden", "Denmark", "Netherlands"];

    for (var i = 0; i < columndata.length; i++) {

        chartdata[i].key = columndata[i];

        chartdata[i].values = csv.map(function(d) {
                return [+d["year"], +d[ columndata[i] ] ];
            })
            .filter(function(d){
                return d[1]||(d[1] === 0);
            });
            //the filter is applied to the mapped array, 
            //and the results are assigned to the values array.
    }
});
person AmeliaBR    schedule 30.01.2014
comment
Спасибо @AmeliaBR! Это работает! (Хотя мне пришлось изменить одну вещь, но я не уверен, почему. Если я использую строку 'return d [1] || (d [1] === 0); », это не сработает (отсутствующие значения включены в загруженные данные). Но если я использую 'return d [1] || (d [1]! = 0);', то он отлично работает! Большое спасибо! Вот результат, если кому-то интересно. - person user2656065; 31.01.2014
comment
Ах я вижу. Когда вы делаете +d[ columndata[i] ], он преобразует нулевые значения в ноль. Так что мои попытки отличить истинные нулевые значения от нулевых значений терпят неудачу еще до того, как вы дойдете до фильтра. Если вы уверены, что у вас никогда не будет действительных нулевых значений, вы можете просто использовать return d[1]; для фильтра. Если вы хотите отделить ноль от нуля, вам также необходимо изменить функцию карты, чтобы использовать parseFloat(d[ columndata[i] ]) вместо оператора преобразования +. parseFloat вернет NaN для нулевых значений или пустых строк; преобразование + возвращает 0. - person AmeliaBR; 01.02.2014