Skip to content

Instantly share code, notes, and snippets.

@GANdalf2357
Last active December 15, 2017 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GANdalf2357/1f8032ed06b365766fd37233b7d1266b to your computer and use it in GitHub Desktop.
Save GANdalf2357/1f8032ed06b365766fd37233b7d1266b to your computer and use it in GitHub Desktop.
Visual Sentiment Comparator

By this flow it is possible to compare the sentiments of twitter streams from two different topics/terms. There are calculated the average scores of the last 10 tweets for each term all the time and visualized in a line chart with an update each second. The terms can be changed over the UI also. Additionally there are displayed the top 10 and the worst 10 tweets scored so far for both terms. Flow created by Benno Geißelmann.

[{"id":"ff2f8615.098e2","type":"twitter in","z":"558ac18.6e701c","twitter":"","tags":"","user":"false","name":"","topic":"tweets","inputs":1,"x":536.3333740234375,"y":368.7777099609375,"wires":[["ed08319.3d6fbd"]]},{"id":"a8c99683.05e568","type":"sentiment","z":"558ac18.6e701c","name":"","x":827.0001220703125,"y":375.44439697265625,"wires":[["5199662f.f92fd8","32c6bfbd.113668"]]},{"id":"bbd3b962.0ff068","type":"ui_chart","z":"558ac18.6e701c","name":"","group":"421cae4c.b21998","order":0,"width":"27","height":"9","label":"Dictionary Sentiment Scores","chartType":"line","legend":"true","xformat":"HH:mm:ss","interpolate":"bezier","nodata":"","dot":false,"ymin":"-4","ymax":"4","removeOlder":"20","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":735.8331909179688,"y":859.6112060546875,"wires":[[],[]]},{"id":"5199662f.f92fd8","type":"function","z":"558ac18.6e701c","name":"term1","func":"msg.term=\"term1\";\n\nreturn msg;","outputs":1,"noerr":0,"x":1125.6668090820312,"y":373.7777099609375,"wires":[["e410bff4.43721"]]},{"id":"457fd2df.52e584","type":"inject","z":"558ac18.6e701c","name":"","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":157.16665649414062,"y":925.9445190429688,"wires":[["cac2cd66.857368","73a7aa3c.ea129c","36829940.28eb86"]]},{"id":"cac2cd66.857368","type":"function","z":"558ac18.6e701c","name":"draw Term1 chart","func":"var term = global.get(\"term1\");\nif(typeof term !==\"undefined\"){\n msg.payload = global.get(\"meanSentiment\"+term);\n msg.topic = term;\n return msg;\n}","outputs":1,"noerr":0,"x":546.1666564941406,"y":798.9445190429688,"wires":[["bbd3b962.0ff068"]]},{"id":"73a7aa3c.ea129c","type":"function","z":"558ac18.6e701c","name":"draw Term2 chart","func":"var term = global.get(\"term2\");\nif(typeof term !==\"undefined\"){\n msg.payload = global.get(\"meanSentiment\"+term);\n msg.topic = term;\n return msg;\n}\n","outputs":1,"noerr":0,"x":542.1666564941406,"y":920.9445190429688,"wires":[["bbd3b962.0ff068"]]},{"id":"fb155085.6f9c68","type":"twitter in","z":"558ac18.6e701c","twitter":"","tags":"","user":"false","name":"","topic":"tweets","inputs":1,"x":535.3333740234375,"y":516.777717590332,"wires":[["9514363c.83a12"]]},{"id":"698286fa.f83d2","type":"ui_text_input","z":"558ac18.6e701c","name":"","label":"Term 2","group":"421cae4c.b21998","order":0,"width":0,"height":0,"passthru":false,"mode":"text","delay":"1000","topic":"","x":205.8333740234375,"y":474.5277404785156,"wires":[["18879738.e71339"]]},{"id":"2b12ec5b.b1ec8c","type":"ui_text_input","z":"558ac18.6e701c","name":"","label":"Term 1","group":"421cae4c.b21998","order":0,"width":0,"height":0,"passthru":false,"mode":"text","delay":"1000","topic":"","x":204.8333740234375,"y":399.7777099609375,"wires":[["142d2bb3.7623b4"]]},{"id":"142d2bb3.7623b4","type":"function","z":"558ac18.6e701c","name":"preprocess","func":"msg.term = msg.payload;\nvar term = msg.term.replace(\" \",\"_\").replace(/[\"']/g, \"\");\nnode.log(\"term is\"+term);\nglobal.set(\"term1\",term);\nreturn msg;","outputs":1,"noerr":0,"x":376.3333740234375,"y":369.77771759033203,"wires":[["ff2f8615.098e2"]]},{"id":"18879738.e71339","type":"function","z":"558ac18.6e701c","name":"preprocess","func":"msg.term = msg.payload;\nvar term = msg.term.replace(\" \",\"_\").replace(/[\"']/g, \"\");\nglobal.set(\"term2\",term);\nreturn msg;","outputs":1,"noerr":0,"x":371.3333740234375,"y":515.777717590332,"wires":[["fb155085.6f9c68"]]},{"id":"de0ca02d.2527c8","type":"sentiment","z":"558ac18.6e701c","name":"","x":819.33349609375,"y":522.1110534667969,"wires":[["df2968fa.a0a53","32c6bfbd.113668"]]},{"id":"df2968fa.a0a53","type":"function","z":"558ac18.6e701c","name":"term2","func":"msg.term=\"term2\";\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1128.6666870117188,"y":520.4443664550781,"wires":[["e410bff4.43721"]]},{"id":"a89135c8.ce2fa8","type":"ui_button","z":"558ac18.6e701c","name":"","group":"421cae4c.b21998","order":0,"width":0,"height":0,"passthru":false,"label":"clear","color":"","bgcolor":"","icon":"","payload":"[]","payloadType":"json","topic":"","x":505.1665954589844,"y":860.9445190429688,"wires":[["bbd3b962.0ff068"]]},{"id":"4bb6800a.990ef8","type":"ui_text","z":"558ac18.6e701c","group":"b428221f.de387","order":0,"width":"24","height":"22","name":"","label":"Top 10 Samples","format":"{{msg.payload}}","layout":"col-center","x":747.1666564941406,"y":1007.9445190429688,"wires":[]},{"id":"36829940.28eb86","type":"function","z":"558ac18.6e701c","name":"print sample table","func":"function createTable(top10_1,flop10_1,top10_2,flop10_2){\n \n var table = \"<table style=\\\"width:100%;font-size:20px;\\\">\";\n table+=\"<tr><th>Rank</th><th>Tweet</th><th>Score</th></tr>\";\n \n if(typeof top10_1!==\"undefined\"){\n for(var i=0;i<top10_1.length;i++){\n table+=\"<tr><td>\"+(i+1)+\"</td><td>\"+top10_1[i].text+\"</td><th>\"+top10_1[i].score+\"</td></tr>\";\n }\n }\n table+=\"</table>\";\n \n table+=\"<p><br><br><table style=\\\"width:100%;font-size:20px;\\\">\";\n table+=\"<tr><th>Rank</th><th>Tweet</th><th>Score</th></tr>\";\n \n if(typeof flop10_1!==\"undefined\"){\n for(var n=0;n<flop10_1.length;n++){\n table+=\"<tr><td>\"+(n+1)+\"</td><td>\"+flop10_1[n].text+\"</td><th>\"+flop10_1[n].score+\"</td></tr>\";\n }\n }\n table+=\"</table>\";\n \n table+= \"<p><br><br><table style=\\\"width:100%;font-size:20px;\\\">\";\n table+=\"<tr><th>Rank</th><th>Tweet</th><th>Score</th></tr>\";\n if(typeof top10_2!==\"undefined\"){\n for(var l=0;l<top10_2.length;l++){\n table+=\"<tr><td>\"+(l+1)+\"</td><td>\"+top10_2[l].text+\"</td><th>\"+top10_2[l].score+\"</td></tr>\";\n }\n }\n table+=\"</table>\";\n \n table+=\"<p><br><br><table style=\\\"width:100%;font-size:20px\\\">\";\n table+=\"<tr><th>Rank</th><th>Tweet</th><th>Score</th></tr>\";\n \n if(typeof flop10_2!==\"undefined\"){\n for(var k=0;k<flop10_2.length;k++){\n table+=\"<tr><td>\"+(k+1)+\"</td><td>\"+flop10_2[k].text+\"</td><th>\"+flop10_2[k].score+\"</td></tr>\";\n }\n }\n table+=\"</table>\";\n \n return table;\n}\nvar term1 = global.get(\"term1\");\nvar term2 = global.get(\"term2\");\nmsg.payload = createTable(global.get(\"top10\"+term1), global.get(\"flop10\"+term1),global.get(\"top10\"+term2), global.get(\"flop10\"+term2));\nreturn msg;","outputs":1,"noerr":0,"x":544.0831909179688,"y":1005.9445190429688,"wires":[["4bb6800a.990ef8"]]},{"id":"eea69e42.c5fcf8","type":"inject","z":"558ac18.6e701c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":167.27777099609375,"y":1113.388951619466,"wires":[["19b180d9.33ae77"]]},{"id":"19b180d9.33ae77","type":"function","z":"558ac18.6e701c","name":"global functions","func":"function update10Function(){\n return ((compare, name, msg)=>{\n var ten = global.get(name);\n if(typeof ten===\"undefined\"){\n ten = [];\n ten.push({\n \"text\":msg.tweet.text,\n \"score\":msg.sentiment.score\n });\n global.set(name,ten);\n //node.log(JSON.stringify(ten));\n }\n else{\n if(containsAlready(msg.tweet.text,ten)){\n return;\n }\n var added = false;\n //node.log(\"start defined: \"+JSON.stringify(ten));\n for(var i=0;i<ten.length;i++){\n if(compare(msg.sentiment.score,ten[i].score)){\n var entry = {\n \"text\":msg.tweet.text,\n \"score\":msg.sentiment.score\n };\n ten.splice(i, 0, entry);\n added=true;\n break;\n }\n }\n if(added===false && ten.length<10){\n ten.push({\n \"text\":msg.tweet.text,\n \"score\":msg.sentiment.score\n });\n }\n ten.splice(10,ten.length-10);\n node.log(\"end\"+JSON.stringify(ten));\n }\n });\n}\n\nfunction containsAlready(tweet, ten){\n var prefix = tweet.substring(0,tweet.length/2);\n return ten.map(e=>e.text).filter(e=>e.indexOf(prefix)>-1).length>0\n}\nglobal.set(\"update10\",update10Function());\nreturn msg;","outputs":1,"noerr":0,"x":397.27777099609375,"y":1115.6389770507812,"wires":[[]]},{"id":"cb43471d.a49f88","type":"inject","z":"558ac18.6e701c","name":"","topic":"","payload":"Microsoft","payloadType":"str","repeat":"","crontab":"","once":true,"x":139.20004272460938,"y":317.74440002441406,"wires":[["142d2bb3.7623b4","2b12ec5b.b1ec8c"]]},{"id":"3f0a858d.3b15b2","type":"inject","z":"558ac18.6e701c","name":"","topic":"","payload":"Uber","payloadType":"str","repeat":"","crontab":"","once":true,"x":152.66668701171875,"y":555.6110687255859,"wires":[["18879738.e71339","698286fa.f83d2"]]},{"id":"e410bff4.43721","type":"function","z":"558ac18.6e701c","name":"calculate average sentiment","func":"var term = global.get(msg.term);\nvar sampleSize = 10;\nvar sentiments = global.get(\"sentiments\"+term);\nif(typeof sentiments ===\"undefined\"){\n sentiments =[];\n global.set(\"sentiments\"+term,sentiments);\n}\nsentiments.push(msg.sentiment.score);\n\nif(sentiments.length>sampleSize){\n sentiments.splice(0,sentiments.length-sampleSize);\n}\n\nvar sum = sentiments.reduce((e,r)=>e+r);\nglobal.set(\"meanSentiment\"+term,sum/sentiments.length);\n\nglobal.get(\"update10\")(((a,b)=>a>b),\"top10\"+term, msg);\nglobal.get(\"update10\")(((a,b)=>a<b),\"flop10\"+term, msg);\n\nmsg.payload = msg.sentiment.score;\n\n\nreturn msg;","outputs":1,"noerr":0,"x":1304.9501342773438,"y":444.0943298339844,"wires":[[]]},{"id":"eb2340c9.9326c","type":"comment","z":"558ac18.6e701c","name":"Inits the globally used functions once at startup","info":"","x":263.99999237060547,"y":1063.4237098693848,"wires":[]},{"id":"f53511.e32942f","type":"comment","z":"558ac18.6e701c","name":"Periodically triggers the drawing","info":"","x":190.24998474121094,"y":854.6737060546875,"wires":[]},{"id":"9884ec41.9ccdd","type":"comment","z":"558ac18.6e701c","name":"Calculates sentiment scores","info":"","x":176.9167022705078,"y":269.2568817138672,"wires":[]},{"id":"ed08319.3d6fbd","type":"function","z":"558ac18.6e701c","name":"filter","func":"var term = global.get(\"term1\");\nif(msg.payload.indexOf(term)!==-1 && msg.lang===\"en\"){\n return msg;\n}\n","outputs":1,"noerr":0,"x":651.5000610351562,"y":309.4444122314453,"wires":[["a8c99683.05e568"]]},{"id":"9514363c.83a12","type":"function","z":"558ac18.6e701c","name":"filter","func":"var term = global.get(\"term2\");\nif(msg.payload.indexOf(term)!==-1 && msg.lang===\"en\"){\n return msg;\n}\n","outputs":1,"noerr":0,"x":636.7500610351562,"y":605.111083984375,"wires":[["de0ca02d.2527c8"]]},{"id":"32c6bfbd.113668","type":"debug","z":"558ac18.6e701c","name":"","active":false,"console":"false","complete":"true","x":959.8215942382812,"y":446.6110534667969,"wires":[]},{"id":"421cae4c.b21998","type":"ui_group","z":"","name":"Compare Sentiments","tab":"2cd5a76b.109eb8","disp":true,"width":"27"},{"id":"b428221f.de387","type":"ui_group","z":"","name":"Samples","tab":"8f4da24a.0719b8","disp":true,"width":"24"},{"id":"2cd5a76b.109eb8","type":"ui_tab","z":"","name":"Sentiment","icon":"dashboard"},{"id":"8f4da24a.0719b8","type":"ui_tab","z":"","name":"Top Tweets","icon":"dashboard"}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment