Reputation: 1196
I've got several related json data files. Without giving too much away about the proprietary data, and to make it simple ...
Say one json file "businesses"
describes businesses, with features being their name, address, etc, and a unique ID. This numbers in the hundreds of thousands.
Then another json file "ratings"
holds the ratings 1-5 for businesses those given by customers, keyed by unique customer ID and the business ID. All the ratings correspond to businesses in "businesses"
(I hope). "ratings"
is a much smaller file and in fact I am using just 1000 of the tens of thousands of ratings I have.
I have some other related files but I'll just limit it to these for now.
Say I make some kind of d3 chart of the ratings, like a bar chart where each vertical bar represents one business and the height is determined by their avg rating.
I want to make it so that when you hover over a bar you can see the business name, for example, and to do that I have to draw from both "businesses"
and "ratings"
. I've only seen examples with one dataset throughout.
I load two datasets and assigning each to a variable:
(Usually I error-check but I'm removing that for simplicity)
var businesses = [];
var ratings = [];
d3.json("data/business.json", function(json) {
businesses = json;
console.log(businesses);
});
d3.json("data/rating.json", function(json) {
ratings = json;
console.log(ratings);
});
Both data sets appear in the console. I make the bars, something like this:
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(ratings)
.enter()
.append("rect")
(more attribs for ht, width, fill, etc.)
I can show the business id:
.append("title").text(function(d) {return "" + d.business_id ;});
but it is just a meaningless string of characters, numbers, hyphens, and underscores.
How might I most efficiently pluck the business name that matches that ID from the businesses array?
I tried
.append("title").text(function(d) {return getBizName(d.business_id); });
which calls
var getBizName = function(bizId) {
var i;
for (i=0; i<businesses.length; i++) {
if (businesses[i].business_id==bizId) return businesses[i].name;
}
};
It doesn't work. I've tried a few approaches and if I get titles to appear at all, they say undefined
. If I type getBizName(some-valid-business-id)
in the console, it says some-valid-business-id is not defined
.
Any ideas? Keep in mind I am new at this so I make a lot of dumb mistakes. I'm also sleepy. Thanks.
Upvotes: 0
Views: 139
Reputation: 2601
Since I don't know the structure of your businesses
and ratings
array, I'm not sure what's wrong with your getBizName
function, but generally, that technique would work fine.
See example here (hovering over bars shows business name): http://jsfiddle.net/n1qnyv9u/
If name
is somewhere else deeper inside the businesses
array, you may be accessing it incorrectly.
Edit: Since you say that businesses
is usually a large dataset and ratings
is much smaller, you may want to use array.map
to update ratings
to include name
ahead of time. That way, you won't have to call getBizName
every time a ratings
bar is hovered over.
After you get the data in businesses
and ratings
, do this:
ratings.map(function(a) {
a.business_name=getBizName(a.bid);
return a;
}
);
Now ratings
includes business_name
. When constructing the title element, just use the business_name
like below:
.append("title").text(function(d) { return d.business_name; });
Updated fiddle here: http://jsfiddle.net/n1qnyv9u/2/
You may also want to look at https://github.com/Caged/d3-tip for better-looking tooltips.
Upvotes: 1