Pergunta

I am doing a project in d3 and am at my wits' end on how to draw a frequency graph for graphing tweets. So, basically, I have a JSON file whose format is like this

{
    "text": "some text here",
    "time": "timestamp here",
    "timezone": "timezone here",
    "retweet_count": some number,
    "hashtags": "some text here"
}

So, now I need to draw a graph in d3 which shows the number of tweets in a particular time period. For example, between date X and date Y, the graph shows how many tweets were there per day.

Can someone help me out with this? I'm really very new to d3.

Foi útil?

Solução

You should be able to use the d3 time scale together with the intervals to do your binning for you. Something like:

var data= [
  {time: 'Jan. 1, 2012 13:00', name:"test", value:2},
  {time: 'Jan. 2, 2012 9:00', name:"test", value:2},
  {time: 'Jan. 3, 2012 14:00', name:"test", value:2},
  {time: 'Jan. 1, 2012 12:30', name:"test", value:2},
  {time: 'Jan. 3, 2012 1:00', name:"test", value:2},
  {time: 'Jan. 3, 2012 1:10', name:"test", value:2},
  {time: 'Jan. 3, 2012 1:20', name:"test", value:2},
  {time: 'Jan. 3, 2012 2:00', name:"test", value:2},
  {time: 'Jan. 1, 2012 3:00', name:"test", value:2},
];

// Get the date range from the data - could also be hardcoded
var dateRange = d3.extent(data, function(d) { return new Date(d.time); });
console.log("Data range", dateRange); // This will output your data's time range

// This will compute time bins
var binner = d3.time.scale();

// Pick the interval I want to bin on
var interval = d3.time.day; // Use hour, or minute, etc.      

// I will compute the number of the time intervals I want  
var allIntervals = interval.range(interval.floor(dateRange[0]), interval.ceil(dateRange[1]));
console.log("Intervals", allIntervals); // This will output an array of all the days/hours/whatever between min and max date

// Input domain mapped to output range
binner.domain([allIntervals[0], allIntervals[allIntervals.length - 1]]);
binner.range([0,allIntervals.length - 1]);

// Make sure we only output integers - important because we will fill an array
binner.interpolate(d3.interpolateRound);

// Empty histogram
var hist = [];
for(var i=0; i < allIntervals.length; i++) hist[i] = 0;

data.forEach(function(d) {
  // Compute the hour index
  var tid = binner(interval.floor(new Date(d.time)));
  console.log("Map " + d.time + " to " + tid);

  if(!hist[tid]) {
    hist[tid] = 1;
  } 
  else { 
    hist[tid]++;
  }
});

// Here is the histogram.
console.log("Hist:",hist);

I put it together with a very rudimentary histogram vis here

Note you could probably replace the interval.range(...) call with some millisecond math instead to improve performance, but having all the values can be useful if you want to do, say, tooltips, for example.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top