I den forrige delen av denne opplæringen så vi hvordan du kommer i gang med D3.js, og opprettet dynamiske skalaer og akser for vår visualiseringsgraf ved hjelp av et prøvedatasett. I denne delen av opplæringen skal vi tegne grafen ved hjelp av prøvedatasettet.
For å komme i gang, klone den forrige opplærings kildekoden fra GitHub.
git klon https://github.com/jay3dec/PythonD3jsMashup_Part2.git
Naviger til Google App Engine (GAE) SDK-katalogen og start serveren.
./dev_appserver.py PythonD3jsMashup_Part2 /
Pek nettleseren din til http: // localhost: 8080 / displayChart, og du bør kunne se X- og Y-aksene som vi opprettet i den forrige opplæringen.
Før du begynner, opprett en ny mal som heter displayChart_3.html
som vil være det samme som displayChart.html
. Legg også til en rute for displayChart_3.html
. Dette er gjort bare for å holde demo av den forrige opplæringen intakt, siden jeg skal være vert for den på samme URL.
klasse DisplayChart3 (webapp2.RequestHandler): def get (selv): template_data = template_path = 'Maler / displayChart_3.html' self.response.out.write (template.render (template_path, template_data)) application = webapp2.WSGIApplication [('/ chart', ShowChartPage), ('/ displayChart', DisplayChart), ('/ displayChart3', DisplayChart3), ('/', ShowHome),] debug = True)
Fra vårt utvalgsdatasett har vi en rekke telle
å bli plottet over et sett med tilsvarende år
.
var data = ["count": "202", "år": "1590", "count": "215", "år": "1592", "count": "179" år ":" 1593 "," år ":" 1594 ", " count ":" 134 "," år " 176 "," år ":" 1596 "," tall ":" 172 "," år ":" 1597 ", teller ":" 199 "," år ":" 1599 ", " telle ":" 181 "," år ":" 1600 ", , "år": "1606", "count": "187", "år": "160", "år" : "1607", "count": "133", "år": "1608", "count": "190", "år": "1609", "count": "175" , "år": "1610", "telle": "91", "år": "1611", "telle": "150", "år": "1612"];
Vi representerer hvert datapunkt som sirkler i vår visualiseringsgraf. D3.js gir API-metoder for å lage forskjellige former og størrelser.
Først bruker vi d3.selectAll til å velge sirkler inne i visualiseringselementet. Hvis ingen elementer blir funnet, returnerer den en tom plassholder hvor vi kan legge til sirkler senere.
var sirkler = vis.selectAll ("sirkel");
Deretter binder vi vårt datasett til sirkler
utvalg.
var sirkler = vis.selectAll ("sirkel"). data (data);
Siden vår eksisterende sirkelvalg er tom, bruker vi enter for å opprette nye sirkler.
. Circles.enter () føyer ( "svg: sirkel")
Deretter definerer vi bestemte egenskaper som avstanden til kretsens sentre fra X (cx
) og Y (cy
) akser, deres farge, deres radius osv. For henting cx
og cy
, vi skal bruke XScale
og ySkala
å transformere året og telle data inn i plottingsområdet og tegne sirkelen i SVG-området. Slik ser koden ut:
var sirkler = vis.selectAll ("sirkel"). data (data); sirkler.enter () .append ("svg: sirkel") .attr ("slag", "svart") // setter sirkelgrensen .attr ("r", 10) // setter radiusen .attr ", funksjon (d) // forvandler årets data slik at den returnerer xScale (d.år); // kan plottes i svg-rom) .attr (" cy ", funksjon (d) // transformer tallet data slik at det returnerer yScale (d.count); // kan plottes i svg-rommet) .stil ("fyll", "rødt") // setter sirkelfargen
Lagre endringer og oppdatere siden din. Du bør se bildet nedenfor:
I den første delen av denne serien, da vi hentet data fra BigQuery, valgte vi ca. 1000 ord.
SELECT word FROM [publicdata: samples.shakespeare] LIMIT 1000
Vi har et datasett som inneholder en liste over alle ordene som vises i hele Shakespeare-arbeidet. Så, for å gjøre visualiseringsappen åpenbar noen nyttig informasjon, endrer vi spørringen vår for å velge antall ganger et bestemt ord, for eksempel Caesar
, vises i Shakespeares arbeid over flere år.
Så logg inn på Google BigQuery, og vi får en skjerm som den som vises nedenfor:
Når vi har logget på Google BigQuery, har vi et grensesnitt der vi kan komponere og sjekke våre SQL-spørringer. Vi ønsker å velge antall ganger et bestemt ord vises i hele Shakespeare-arbeidet.
Så vår grunnleggende spørring vil se slik ut:
SELECT SUM (word_count) som WCount, corpus_date FRA [publicdata: samples.shakespeare] WHERE word = "Caesar" GRUPPE AV corpus_date ORDER BY WCount
Ovennevnte spørring gir oss et resultatsett som vist nedenfor:
La oss også inkludere gruppen av arbeider som svarer til Word Count. Endre spørringen som vist å inkludere corpus:
SELECT SUM (word_count) som WCount, corpus_date, group_concat (corpus) som Arbeid FRA [publicdata: samples.shakespeare] WHERE word = "Caesar" og corpus_date> 0 GROUP BY corpus_date ORDER BY WCount
Det resulterende resultatsettet er vist nedenfor:
Deretter åpne app.py
og opprett en ny klasse som heter GetChartData
. Inne i det, ta med spørringsoppgaven vi opprettet ovenfor.
queryData = 'query': 'VELG SUM (word_count) som WCount, corpus_date, group_concat (corpus) som Work FROM "[publiseringsdata: samples.shakespeare] WHERE word =" God "og corpus_date> 0 GROUP BY corpus_date ORDER BY WCount'
Deretter oppretter du en BigQuery-tjeneste som vi vil utføre vår queryData
.
tableData = bigquery_service.jobs ()
Nå, utfør queryData
mot BigQuery-tjenesten og skrive ut resultatet til siden.
dataList = tableData.query (projectId = PROJECT_NUMBER, body = queryData) .execute () self.response.out.write (dataList)
Inkluder også en ny rute for GetChartData
som vist.
søknad = webapp2.WSGIApplication ('/ getChartData', GetChartData), ('/', ShowHome), ('/ displayChart', DisplayChart), ('/ displayChart3', DisplayChart3) ,], debug = True)
Endelig oppdater koden til GAE-plattformen.
./appcfg.py oppdatering PythonD3jsMashup_Part2 /
Pek nettleseren din til http://YourAppspotUrl.com/getChartData som skal vise de resulterende dataene fra BigQuery.
Deretter prøver vi å analysere dataene som er mottatt fra Google BigQuery, og konvertere det til et JSON-dataobjekt og sende det til klientsiden for å behandle ved hjelp av D3.js.
Først vil vi sjekke om det er noen rader i Datalist
returnert. Hvis ingen rader, setter vi svaret som null eller null.
hvis 'rader' i dataList: # parse dataList annet: resp.append ('count': '0', 'year': '0', 'corpus': '0')
Deretter analyserer vi Datalist
ved å løse hver rad og plukke opp telling, år og corpus og opprette vårt nødvendige JSON objekt.
resp = [] hvis 'rader' i dataliste: for rad i dataListe ['rader']: for nøkkel, dict_list i row.iteritems (): count = dict_list [0] år = dict_list [1] corpus = dict_list [2] resp.append ('count': count ['v'], 'year': år ['v'], 'corpus': corpus ['v']) annet: resp.append ('count' '0', 'år': '0', 'corpus': '0')
Siden vi returnerer de analyserte dataene som JSON, importerer du JSON-biblioteket
importer json
Og returner den opprettede responsen som et JSON-svar.
self.response.headers ['Content-Type'] = 'application / json' self.response.out.write (json.dumps (resp))
La oss også gjøre søkeordet dynamisk, slik at det kan bestå som en parameter.
inputData = self.request.get ("inputData") queryData = 'query': 'VELG SUM (word_count) som WCount, corpus_date, group_concat (corpus) som arbeid fra "[publicdata: samples.shakespeare] WHERE word ="' + inputData + '"og corpus_date> 0 GROUP BY corpus_date ORDER BY WCount'
Her er hvordan klassen GetChartData
endelig ser ut:
klasse GetChartData (webapp2.RequestHandler): def get (selv): inputData = self.request.get ("inputData") queryData = 'query': 'VELG SUM (word_count) som WCount, corpus_date, group_concat (corpus) som Work FRA "[publicdata: samples.shakespeare] WHERE word =" '+ inputData +' "GROUP BY corpus_date ORDER BY WCount ' tableData = bigquery_service.jobs () dataList = tableData.query (projectId = PROJECT_NUMBER, body = queryData) .execute ) resp = [] hvis 'rader' i dataListe: for rad i dataListe ['rader']: for nøkkel, dict_list i row.iteritems (): count = dict_list [0] år = dict_list [1] corpus = dict_list [2 ] resp.append ('count': count ['v'], 'year': år ['v'], 'corpus': corpus ['v']) annet: resp.append : '0', 'år': '0', 'corpus': '0') self.response.headers ['Content-Type'] = 'application / json' self.response.out.write (json. fyllinger (resp))
Oppdater appen i GAE og pek nettleseren din til http://YourAppspotUrl.com/getChartData og du kan se det returnerte JSON-svaret.
Deretter oppretter vi et grensesnitt for å spørre Google BigQuery-datasettet fra vår app dynamisk. Åpne opp Maler / displayChart_3.html
og inkludere en innboks boks der vi legger inn søkeord for å spørre datasettet.
Inkluder et jQuery-skript på siden og på DOM-klare hendelsen, vi vil spørre Python-metoden GetChartData
på Skriv inn nøkkel
trykk.
$ (dokument) .ready (funksjon () $ ("# txtKeyword"). opptasting (funksjon (hendelse) hvis (event.keyCode == 13) // Hvis du skriver inn tasten, trykk DisplayChart ();); InitChart (); // Init Chart with Axis);
Opprett en annen funksjon DisplayChart
på klientsiden, innenfor som vi lager et Ajax-anrop til Python GetChartData
metode.
funksjon DisplayChart () var søkeord = $ ('# txtKeyword') .val (); $ .ajax (type: "GET", url: "/ getChartData", data: inputData: keyword, dataType: "json", suksess: funksjon (svar) console.log (respons);, feil: funksjon (xhr, errorType, unntak) console.log ('Feil oppstod'););
Oppdater koden til GAE og pek nettleseren din til http://YourAppspotUrl.com/displayChart3. Skriv inn et søkeord, si Caesar
, og trykk Tast inn. Sjekk nettleserkonsollen, og du bør se det returnerte JSON-svaret.
La oss da plotte kretsene ved hjelp av det returnerte svaret. Så opprett en annen JavaScript-funksjon kalt CreateChart
. Denne funksjonen ligner på InitChart
funksjonen, men dataene ville bli sendt som parameter. Slik ser det ut:
funksjon CreateChart (data) var vis = d3.select ("# visualisering"), WIDTH = 1000, HEIGHT = 500, MARGINS = topp: 20, høyre: 20, bunn: 20, venstre: 50, xScale = d3 .scale.linear () .område ([MARGINS.left, WIDTH - MARGINS.right]) .domæne ([d3.min (data, funksjon (d) return (parseInt (d.year, 10) - 5); ), d3.max (data, funksjon (d) return parseInt (d.year, 10);)]), yScale = d3.scale.linear (). rekkevidde ([HEIGHT - MARGINS.top, MARGINS. bunn]). domenet (d3.min (data, funksjon (d) return (parseInt (d.count, 10) - 5);), d3.max (data, funksjon (d) return parseInt .count, 10);)]), xAxis = d3.svg.axis () .scale (xScale), yAxis = d3.svg.axis () .scale (yScale) .orient ("left"); vis.append ("svg: g") .attr ("klasse", "x-akse") .attr ("transform", "oversette (0," + (HEIGHT - MARGINS.bottom) + ")") (x-akse); vis.append ("svg: g") .attr ("klasse", "y-akse") .attr ("transform", "translate (" + (MARGINS.left) + ", 0)") .call (yAxis ); var sirkler = vis.selectAll ("sirkel"). data (data); sirkler.enter () .append ("svg: sirkel") .attr ("slag", "svart") .attr ("r", 10) .attr ("cx", funksjon (d) return xScale .år);) .attr ("cy", funksjon (d) return yScale (d.count);) .style ("fyll", "rødt")
Fra InitChart
funksjon, fjern sirkelopprettingsdelen siden det ikke vil være nødvendig nå. Her er hvordan InitChart
utseende:
funksjonen InitChart () var data = ["count": "202", "år": "1590", "count": "215", "år": "1592", "count" "179", "år": "1593", "tall": "199", "år": "1594", "teller": "176", "år": "1596", "telle": "172", "år": "1597", "telle": "161", "år": "1598 "", "år": "1600", "teller": "157", "år": "1599", ":" 1602 ", " count ":" 179 "," år ":" 1603 ", " count ":" 150 "," år ":" 1606 ", " count ":" 187 "," år ":" 1607 ", " count ":" 133 "," år ":" 1608 ", " count ":" 190 "," år ":" 1609 " ":" 175 "," år ":" 1610 ", " count ":" 91 "," år ":" 1611 ", " count ":" 150 "," år ":" 1612 " ]; var farge = d3.scale.category20 (); var vis = d3.select ("# visualisering"), WIDTH = 1000, HEIGHT = 500, MARGINS = topp: 20, høyre: 20, bunn: 20, venstre: 50, xScale = d3.scale.linear .range ([MARGINS.left, WIDTH - MARGINS.right]) .domæne ([d3.min (data, funksjon (d) return (parseInt (d.year, 10) - 5);), d3.max (data, funksjon (d) return parseInt (d.year, 10);)]), yScale = d3.scale.linear () .område ([HEIGHT - MARGINS.top, MARGINS.bottom]). [d3.min (data, funksjon (d) return (parseInt (d.count, 10) - 5);), d3.max (data, funksjon (d) return parseInt (d.count, 10); )]), xAxis = d3.svg.axis () .scale (xScale), yAxis = d3.svg.axis () .scale (yScale) .orient ("left"); vis.append ("svg: g") .attr ("klasse", "x-akse") .attr ("transform", "oversette (0," + (HEIGHT - MARGINS.bottom) + ")") (x-akse); vis.append ("svg: g") .attr ("klasse", "y-akse") .attr ("transform", "translate (" + (MARGINS.left) + ", 0)") .call (yAxis );
Fra nå av, når vi laster inn / displayChart3
siden, vil sirkler ikke vises. Sirkler vil bare vises når søkeordet er søkt. Så på suksess tilbakeringing av DisplayChart
Ajax-anrop, send svaret på CreateChart
funksjon.
suksess: funksjon (respons) console.log (respons); CreateChart (respons);
Oppdater koden til GAE og prøv å søke etter søkeordet Caesar
. OK, så nå får vi se resultatet som sirkler på grafen. Men det er ett problem: begge aksene blir overskrevet.
Så for å unngå at vi skal sjekke inn i CreateChart
Fungerer hvis aksene allerede er der eller ikke.
var hasAxis = vis.select ('axis') [0] [0]; hvis (! hasAxis) vis.append ("svg: g") .attr ("klasse", "x-aksen") .attr ("transform", "translate (0," + (HEIGHT - MARGINS.bottom) + ")") .call (xAxis); vis.append ("svg: g") .attr ("klasse", "y-akse") .attr ("transform", "translate (" + (MARGINS.left) + ", 0)") .call (yAxis );
Som du kan se, har vi bare sjekket om SVG-elementet har akser, og hvis ikke, oppretter vi dem igjen. Oppdater koden til GAE, og prøv å søke på nytt for søkeordet, og du bør se noe slikt:
Selv om alle ser bra ut nå, er det fortsatt noen få problemer som vi skal ta opp i neste del av denne opplæringen. Vi vil også introdusere D3.js-overganger og noen få funksjoner til vår D3.js-graf, og prøve å gjøre det mer interaktiv.
Kildekoden fra denne opplæringen er tilgjengelig på GitHub.