2012-08-06 14 views
15

Ich passe die Crossfilter Bibliothek an, um einige Tweets zu visualisieren, die ich von der Olympics gesammelt habe. Ich versuche, das anfängliche Beispiel auf zwei Arten im Wesentlichen zu erstrecken:Histogramme neu zeichnen mit Crossfilter und D3

  1. Statt auf dem Original-Datensatz basierend Listen der Flüge angezeigt wird, möchte ich zur Zeit von crossfilter ausgewählt von Artikel verkeilte in einer anderen Daten-Set-Listen der Elemente anzuzeigen.
  2. Wechseln Sie zwischen verschiedenen Datenquellen und laden Sie die Histogramme und Tabellen neu.

Ich habe Teil (1) funktioniert wie geplant. Teil (2) bereitet mir jedoch Probleme. Ich ändere gerade den Datensatz, indem ich entweder einen neuen "Sport" auswähle, um einen neuen Zusammenfassungsalgorithmus anzuzeigen oder auszuwählen. Wenn ich eine dieser Optionen auswähle, sollte ich zunächst die zuvor erstellten und angezeigten Filter, Diagramme und Listen entfernen und dann die neuen Daten neu laden.

Allerdings, etwas neu zu Front-End-Visualisierungen, vor allem D3 und Crossfilter, habe ich nicht herausgefunden, wie dies zu tun, noch bin ich sicher, wie man die Frage am besten formuliert.

Ich habe ein funktionierendes Beispiel für mein Problem here. Wählen Sie einen Bereich am Datum aus und wechseln Sie dann von Bogenschießen zu Fechten. Wenn Sie dann auf Zurücksetzen klicken, wird ein gutes Beispiel angezeigt: Nicht alle neuen Daten werden geplottet.

Screen image of Fencing data after switching sports while filtering on Date

Wie gesagt, die meisten der Codeform des Crossfilter Beispiel und eine Tutorial on making radial visualizations gezogen wird. Hier einige der wichtigsten Code Brocken, die ich denke, sind relevant:

eine neue Datenquelle auswählen:

d3.selectAll("#sports a").on("click", function (d) { 
    var newSport = d3.select(this).attr("id"); 
    activate("sports", newSport); 
    reloadData(activeLabel("sports"), activeLabel("methods")); 
});       

d3.selectAll("#methods a").on("click", function (d) { 
    var newMethod = d3.select(this).attr("id"); 
    activate("methods", newMethod); 
    reloadData(activeLabel("sports"), activeLabel("methods")); 
}); 

die Daten Nachladen:

function reloadData(sportName, methodName) { 
    var filebase = "/tweetolympics/data/tweet." + sportName + "." + methodName + ".all."; 
    var summaryList, tweetList, remaining = 2; 
    d3.csv(filebase + "summary.csv", function(summaries) { 
     summaries.forEach(function(d, i) { 
      d.index = i; 
      d.group = parseInt(d.Group); 
      d.startTime = parseTime(d.Start); 
      d.meanTime = parseTime(d.Mean); 
     }); 
     summaryList = summaries; 
     if (!--remaining) 
      plotSportData(summaryList, tweetList); 
    }); 

    d3.csv(filebase + "groups.csv", function(tweets) { 
     tweets.forEach(function(d, i) { 
      d.index = i; 
      d.group = parseInt(d.Group); 
      d.date = parseTime(d.Time); 
     }); 
     tweetList = tweets; 
     if (!--remaining) 
      plotSportData(summaryList, tweetList); 
    }); 
} 

Und das Kreuz Filter Laden der Daten mit:

function plotSportData(summaries, tweets) { 

    // Create the crossfilter for the relevant dimensions and groups. 
    var tweet = crossfilter(tweets), 
     all = tweet.groupAll(), 
     date = tweet.dimension(function(d) { return d3.time.day(d.date); }), 
     dates = date.group(), 
     hour = tweet.dimension(function(d) { return d.date.getHours() + d.date.getMinutes()/60; }), 
     hours = hour.group(Math.floor), 
     cluster = tweet.dimension(function(d) { return d.group; }), 
     clusters = cluster.group(); 

    var charts = [ 
     // The first chart tracks the hours of each tweet. It has the 
     // standard 24 hour time range and uses a 24 hour clock. 
     barChart().dimension(hour) 
        .group(hours) 
        .x(d3.scale.linear() 
          .domain([0, 24]) 
          .rangeRound([0, 10 * 24])), 
     // more charts added here similarly... 
     ]; 

    // Given our array of charts, which we assume are in the same order as the 
    // .chart elements in the DOM, bind the charts to the DOM and render them. 
    // We also listen to the chart's brush events to update the display. 
    var chart = d3.selectAll(".chart") 
        .data(charts) 
        .each(function(chart) { chart.on("brush", renderAll) 
               .on("brushend", renderAll); }); 

    // Render the initial lists. 
    var list = d3.selectAll(".list") 
       .data([summaryList]); 

    // Print the total number of tweets. 
    d3.selectAll("#total").text(formatNumber(all.value())); 

    // Render everything.. 
    renderAll(); 

Meine Vermutung ist, dass ich plotSportData mit etwas starten sollte Löscht den alten Datensatz, aber ich bin mir nicht sicher, wie das aussehen soll. Irgendwelche Vorschläge oder Gedanken würden sehr geschätzt werden.

Antwort

12

Nach einer Nacht Schlaf kam die Lösung zu mir.

Ich brauche nur

d3.selectAll(".chart").selectAll("svg").remove(); 

am Anfang plotSportData zu nennen, die alle Histogramme greifen werden unter dem .chart divs verschachtelt und entfernen. Und wenn es keine Elemente zu entfernen gibt, wird es ein No-Op sein.

+3

Vielen Dank für die Freigabe, es gibt nicht viele verfügbare Beispiele für Crossfilter. Viel Glück mit Ihrem Projekt. –

Verwandte Themen