Search code examples
d3.jsreferenceerror

An error with opening Multi-Series Line Chart from Mike Bosktok


I'm practicing d3 with Mike Bostok's example: https://bl.ocks.org/mbostock/3884955

I'd like to see how the series that he made - cities - looks like.

I opened the html file using Python local server and in the console, I wrote 'console.log(cities);' but it didn't work. 'console.log(data);' also didn't work. They all showed this error message:

VM100:1 Uncaught ReferenceError: cities is not defined
    at <anonymous>:1:13

I didn't make any modification in his code. So I don't think there is an error in the code. I assume perhaps the problem is in line with d3 setting? So, I've tried to open the file in Firefox and I've also downloaded d3 but those two ways also didn't work.

Does anyone happen to know what is the cause of the problem? If someone can explain how the 'cities' in his code looks like, then you are the most welcome!

Thanks a lot,


Solution

  • At a guess, the reason cities is undefined is because your console.log statement is somewhere outside of the callback function provided to d3.tsv. If you look closely at Mike's code, you'll notice that the third argument to d3.tsv is a function that receives as an argument an error object and the processed data. Inside that function, he defines the cities variable, so if you put console.log(cities) anywhere outside of that function, cities will be undefined.

    Now, on to the format of the data. If you look further down that block, there's another file: data.tsv. It has four columns: date, New York, San Francisco, Austin. d3.tsv will create an array where each element in the array corresponds to one row in the TSV (except for the header row). Each row is converted to a plain JavaScript Object with properties that correspond to the columns of the file. That array is passed into the callback as the data variable in this block. So data[0] will be

    {
      "date": "20111001",
      "New York": "63.4",
      "San Francisco": "62.7",
      "Austin": "72.2"
    }
    

    When the cities variable is defined, that array is transformed into an array that contains one item per city, and each object representing the city contains the time-series data of temperature for that city. So the cities variable will look like:

    [
      {
        "id": "New York",
        "values": [
          {"date": Date 2011-10-01T00:00:00, "temperature": 63.4},
          {"date": Date 2011-10-02T00:00:00, "temperature": 48.0},
          ...
        ]
      },
      {
        "id": "San Francisco",
        "values": [...]
      },
      {
        "id": "Austin",
        "values": [...]
      }
    ]
    

    It's probably worth pointing here the second argument to d3.tsv in this example: the type function. This is where all the strings are converted into Date or Number objects. Without this argument, all of the property values in data would be strings.

    For more information on how d3.tsv works, you can check the docs for d3-request.

    CAVEAT: that block is for d3v4, the latest version of d3 is v5. In v5, d3-request is deprecated in favor of d3-fetch. d3-fetch provides pretty much the same set of utilities for fetching data, but instead of using callback functions, they return Promises.