2015-12-05 4 views
0

Я довольно новичок в d3.js и в Интернете. Я хотел и^файл CSV, чтобы построить линейный график, но я получил некоторые ошибки я не могу исправить:D3.js Невозможно прочитать свойство 'length' of undefined

enter image description here

Вот код:

body,html{ 
 
\t margin: 0; 
 
\t padding: 0; 
 
\t font-family: "Arial", sans-serif; 
 
\t font-size: 0.95em; 
 
\t text-align: center; 
 
} 
 
#chart{ 
 
\t background-color: #F5F2EB; 
 
\t border: 1px solid #CCC; 
 
} 
 
.bar{ 
 
\t fill: purple; 
 
\t shape-rendering: crispEdges; 
 
} 
 
.bar-label{ 
 
\t fill: black; 
 
\t text-anchor: middle; 
 
\t font-size: 18px; 
 
} 
 
.axis path, 
 
.axis line{ 
 
\t fill: none; 
 
\t stroke: #000; 
 
\t shape-rendering: crispEdges; 
 
} 
 
.gridline path, 
 
.gridline line{ 
 
\t fill: none; 
 
\t stroke: #ccc; 
 
\t shape-rendering: crispEdges; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<!DOCTYPE html> 
 
<html lang="en"> 
 
<head> 
 
\t <meta charset="UTF-8"> 
 
\t <title>Learning D3</title> 
 
\t <link rel="stylesheet" href="main.css"> 
 
\t <script type="text/javascript" src="d3.min.js"></script> 
 
</head> 
 
<body> 
 
<!--Place all DOM elements here --> 
 
<script> 
 

 
var data= [ 
 
\t d3.csv("refugee_data.csv", function(d) { 
 
    return { 
 
    /*year: new Date(+d.Year, 0, 1), // convert "Year" column to Date 
 
    make: d.Make, 
 
    model: d.Model, 
 
    length: +d.Length // convert "Length" column to number*/ 
 
\t \t date: d.Year + "/" +d.Month, 
 
\t \t origin: d.Origin, 
 
\t \t asylum: d.Asylum, 
 
\t \t value: +d.Value 
 
    }; 
 
}, function(error, rows) { 
 
    console.log(rows); 
 
}) 
 
]; 
 

 
var w = 800; 
 
var h = 450; 
 
var margin = { 
 
\t top: 58, 
 
\t bottom: 100, 
 
\t left: 80, 
 
\t right: 40 
 
}; 
 
var width = w - margin.left - margin.right; 
 
var height = h - margin.top - margin.bottom; 
 

 
var svg = d3.select("body").append("svg") 
 
\t \t \t .attr("id", "chart") 
 
\t \t \t .attr("width", w) 
 
\t \t \t .attr("height", h); 
 
var dateParser = d3.time.format("%Y/%B").parse; 
 
var x = d3.time.scale() 
 
\t \t .domain(d3.extent(data, function(d){ 
 
\t \t \t var date = dateParser(d.date); 
 
\t \t \t return date; 
 
\t \t })) 
 
\t \t .range([0,width]); 
 

 
var y = d3.scale.linear() 
 
\t \t .domain([0, d3.max(data, function(d){ 
 
\t \t \t return d.value; 
 
\t \t })]) 
 
\t \t .range([height,0]); 
 

 
function plot(params){ 
 
\t \t //enter() 
 
\t \t this.selectAll(".point") 
 
\t \t \t \t .data(params.data) 
 
\t \t \t \t .enter() 
 
\t \t \t \t \t .append("circle") 
 
\t \t \t \t \t .classed("point", true) 
 
\t \t \t \t \t .attr("r", 2); 
 
\t \t //Update 
 
\t \t this.selectAll(".point") 
 
\t \t .attr("cx", function(d){ 
 
\t \t \t var date = dateParser(d.date); 
 
\t \t \t return x(date); 
 
\t \t }) 
 
\t \t .attr("cy", function(d){ 
 
\t \t \t return y(d.value); 
 
\t \t }) 
 

 
\t \t //Exit() 
 
\t \t this.selectAll(".point") 
 
\t \t .data(params.data) 
 
\t \t .exit() 
 
\t \t .remove(); 
 
} 
 
plot.call(chart, { 
 
\t data: data 
 
}) 
 
</script> 
 
</body> 
 
</html>

И это моя часть моего csv, довольно базовая, поэтому я не понимаю, почему она не работает.

Asylum, Происхождение, год, месяц, стоимость

Германия, Афганистан, 2014, январь, +981 Германия, Афганистан, 2014, февраль, +781 Германия, Афганистан, 2014, март, 675 Германия, Афганистан , 2014, апрель, +673 Германия, Афганистан, 2014, май, 523 Германия, Афганистан, 2014, июнь, 621 Германия, Афганистан, 2014, июль, 752 Германия, Афганистан, 2014, август, 743 Германия, Афганистан , 2014, сентябрь, 922

Я предполагаю, что это действительно ошибка вверху вы можете помочь мне?

+0

Вы отлаживаете свой код и знаете, на какой строке вы получаете ошибку? – Arg0n

+0

консоль сказать что-то в строке 93 или 94 – basedian

ответ

1

Ваша ошибка в том, что вызов d3.csv(...) возвращает ваши данные CSV.

d3.csv выполняет вызов AJAX для загрузки ваших данных, а затем вызывает функцию обратного вызова, когда эти данные были загружены. Ваш код продолжает работать, пока данные загружаются в фоновом режиме. Когда вы пишете var data = [d3.csv(...)], data не содержит данных, загружаемых из файла CSV, он содержит только объект d3, и вы не можете его построить.

Вместо этого, ваш призыв к d3.csv должен выглядеть примерно следующее:

d3.csv("refugee_data.csv", function(d) { 
    return { 
     date: d.Year + "/" +d.Month, 
     origin: d.Origin, 
     asylum: d.Asylum, 
     value: +d.Value 
    }; 
}, function(error, rows) { 
    console.log(rows); 
    render(rows); 
}); 

где render это функция, которая d3 призовет обратить график, когда данные по окончании загрузки.

Я создал render функцию, которая содержала содержимое вашего кода от линии var w = 800; к линиям, начиная var y = ..., а затем содержимое функции plot. Я также заменил this.selectAll на svg.selectAll и удалил использование plot.call. Функция render я писал в конечном итоге следующим образом:

function render(data) { 
    var w = 800; 
    var h = 450; 
    var margin = { 
     top: 58, 
     bottom: 100, 
     left: 80, 
     right: 40 
    }; 
    var width = w - margin.left - margin.right; 
    var height = h - margin.top - margin.bottom; 

    var svg = d3.select("body").append("svg") 
       .attr("id", "chart") 
       .attr("width", w) 
       .attr("height", h); 
    var dateParser = d3.time.format("%Y/%B").parse; 
    var x = d3.time.scale() 
      .domain(d3.extent(data, function(d){ 
       var date = dateParser(d.date); 
       return date; 
      })) 
      .range([0,width]); 

    var y = d3.scale.linear() 
      .domain([0, d3.max(data, function(d){ 
       return d.value; 
      })]) 
      .range([height,0]); 

     //enter() 
     svg.selectAll(".point") 
       .data(data) 
       .enter() 
        .append("circle") 
        .classed("point", true) 
        .attr("r", 2); 
     //Update 
     svg.selectAll(".point") 
     .attr("cx", function(d){ 
      var date = dateParser(d.date); 
      return x(date); 
     }) 
     .attr("cy", function(d){ 
      return y(d.value); 
     }) 

     //Exit() 
     svg.selectAll(".point") 
     .data(data) 
     .exit() 
     .remove(); 
} 

После внесения этих изменений я был в состоянии видеть свой график работать.

+0

Спасибо, это сработало. Есть ли что-то помимо d3.keys для фильтрации некоторых записей csv? Я хочу отфильтровать страны происхождения, такие как афганистан, сирию для взаимных целей. В других терминах я хотел бы навеститься с мусом по точкам, чтобы получить страну происхождения. [Это источник] (http://popstats.unhcr.org/en/asylum_seekers_monthly), чтобы получить представление о реальных данных. – basedian

+0

@basedian: если у вас есть отдельный вопрос, вам нужно задать отдельный вопрос ,Это я вижу, что [вы уже сделали] (http://stackoverflow.com/questions/34110708/d3-js-csv-filter-for-interactivity). –