我正在弄乱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.name
,d.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。
答案 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>
我想做的主要事情是:
script
提取user's top 10 (or 20, or whatever) artists的JSON。d3.json
调用以获取artist's top tags。tag
合并到每位艺术家的原始顶级艺术家JSON中。 (艺术家可以使用许多用户编写的tags
,因此我只会使用最常用的一种。)在实践中,这意味着首先要对{1}}首席艺术家d3.json
进行调用,并在其中进行topArtists
来电 - 其中每个queue.js
是queue.defer()
JSON中的函数。接下来,我可以循环浏览,将topArtists
添加到每个tag
项目,然后使用topArtists
将d3.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()