d3.js:嵌套数据 - 所有数据的键返回未定义

时间:2014-11-08 07:50:31

标签: d3.js

我正在弄乱last.fm API。我正在拉user's top artists data,它返回一个像这样的JSON:

{   "artist": [
      {
        "name": "Kanye West",
        "playcount": "282",
        "mbid": "164f0d73-1234-4e2c-8743-d77bf2191051",
        "url": "http:\/\/www.last.fm\/music\/Kanye+West",
        "streamable": "0",
        "@attr": {
          "rank": "1"
        }
      },
      {
        "name": "Childish Gambino",
        "playcount": "148",
        "mbid": "7fb57fba-a6ef-44c2-abab-2fa3bdee607e",
        "url": "http:\/\/www.last.fm\/music\/Childish+Gambino",
        "streamable": "0",
        "@attr": {
          "rank": "2"
        }
      },

等等。经过一番摆弄后,我为an artist's popular tags(例如摇滚,流行,嘻哈)拉出第二个JSON,循环浏览每个艺术家,并将他们最受欢迎的标签推送到原始数据集。所以现在我的JSON看起来像:

{   "artist": [
      {
        "name": "Kanye West",
        "playcount": "282",
        "mbid": "164f0d73-1234-4e2c-8743-d77bf2191051",
        "url": "http:\/\/www.last.fm\/music\/Kanye+West",
        "streamable": "0",
        "@attr": {
          "rank": "1"
        },
        "tag": "hip hop",
      },
      {
        "name": "Childish Gambino",
        "playcount": "148",
        "mbid": "7fb57fba-a6ef-44c2-abab-2fa3bdee607e",
        "url": "http:\/\/www.last.fm\/music\/Childish+Gambino",
        "streamable": "0",
        "@attr": {
          "rank": "2"
        },
        "tag": "hip hop",
      },

我要做的下一件事是使用d3.nest使用每个标记(流派)作为关键字来汇总我的数据。我正在关注这个tutorial。我的最终目标是制作一个sunburst,内圈上有流派(例如你听多少嘻哈,独立,流行音乐?)和 - 也许点击一下 - 你听的每个艺术家有多少(例如Kanye West vs. Childish Gambino)。

主要问题在于:

        var dataset = d3.nest()
                        .key(function(d) { 
                            return d.tag; 
                        })
                        .entries(topArtists);

key正在为所有数据点返回undefined。当我尝试其他可能的密钥(d.named.streamable)时,它们可以正常工作。我的数据按需扩展。所以它与tag有关 - 这是我推送到topArtists数据集的对象。我不确定发生了什么。这是我如何循环并将艺术家信息与标签信息相结合:

    //Merge
    topArtists.forEach(function(d) {

        //loop through each of the top 10 artists selected
        //pull their mbid (musicbrainz id) and plug it into the var for tags            
        tags = 'http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&mbid='+ d.mbid + '&api_key=[my api key]&format=json';

            //pull that JSON
            d3.json(tags, function(error, tag) {

                if (error) { return console.log(error); };

                //capture only the most commonly used tag (artistTag)
                //and also clean it up a bit
                artistTag = tag.toptags.tag[0].name.toLowerCase().split('-').join(' ');

                //push that string value to the original JSON
                d["tag"] = artistTag;


            }); // close tags JSON call 
        }); //close topArtists loop 

关闭这些循环后,如果我console.log(topArtists),它看起来都很好 - 标签已被添加。 JSFiddle here

1 个答案:

答案 0 :(得分:0)

感谢Lars's suggestion yesterday,我使用Mike Bostock的queue.js库成功完成了这项工作。如果其他人遇到这个问题,这是我遵循的步骤:

首先,我在queue.js电话后<head>呼叫d3.js

            <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
            <script src="http://d3js.org/queue.v1.min.js"></script>

我想做的主要事情是:

  1. 用户输入last.fm用户名。
  2. script提取user's top 10 (or 20, or whatever) artists的JSON。
  3. 拉出&#34; musicbrainz id&#34; (每个艺术家的唯一数字标识符),并执行一系列10(或20或其他)额外的d3.json调用以获取artist's top tags
  4. 将最常用的tag合并到每位艺术家的原始顶级艺术家JSON中。 (艺术家可以使用许多用户编写的tags,因此我只会使用最常用的一种。)
  5. 下一步 - 可视化。
  6. 在实践中,这意味着首先要对{1}}首席艺术家d3.json进行调用,并在其中进行topArtists来电 - 其中每个queue.jsqueue.defer() JSON中的函数。接下来,我可以循环浏览,将topArtists添加到每个tag项目,然后使用topArtistsd3.nest周围的数据排列为tags

    这就是它的全貌:

    首先,keys的外部JSON调用。我这样做是为了将topArtists设置为JSON,否则,如果我尝试将其嵌套在topArtists中,我最终会得到无限循环。

    queue.js

    接下来,在this StackOverflow Q&A之后,我设置了d3.json(top, function(error, json) { if(error) { return console.log(error); } topArtists = json.topartists.artist; ,其中(1)再次从last.fm API调用相同的queue() JSON(这是topArtists我将使用前进来构建我的最终数据集),然后(2)动态调用每个艺术家的topArtists API。

    tags

    在加载了所有这些JSON之后,我遍历并(在检查名称匹配后),将每个艺术家的标记附加到 var q = queue() .defer(d3.json, top); topArtists.forEach(function(d) { tags = 'http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&mbid='+ d.mbid + '&api_key=[my api key]&format=json' q.defer(d3.json, tags); }); 数据,重命名为topArtists

    dataset

    在不关闭 q.awaitAll(function() { dataset = arguments[1][0].topartists.artist for (var i = 1; i < arguments[1].length ; i++) { var j = i - 1; var artistName = arguments[1][0].topartists.artist[j].name; var artistTagName = arguments[1][i].toptags['@attr'].artist; if ( artistName == artistTagName ) { artistTag = arguments[1][i].toptags.tag[0].name.toLowerCase().split('-').join(' '); dataset[j]["tag"] = artistTag; }; }; //close for loop 的情况下,我现在可以使用queue.awaitAll()来汇总我的数据。 d3.nest现已准备好用于可视化;也将在dataset内调用。

    .awaitAll()