Using Clojure for Sentiment Analysis of the Twittersphere

128
Sentiment Analysis of the Twittersphere @APassionForCode

description

Sentiment analysis of online social networks, such as Twitter, is a rapidly growing research area with an increasing number of applications such as: informing disaster response; tracking spread of contagious disease; early forecast of civil unrest. This talk will present an approach for building scalable social media analysis platforms in Clojure

Transcript of Using Clojure for Sentiment Analysis of the Twittersphere

Page 1: Using Clojure for Sentiment Analysis of the Twittersphere

Sentiment Analysis of the Twittersphere

@APassionForCode

Page 2: Using Clojure for Sentiment Analysis of the Twittersphere
Page 3: Using Clojure for Sentiment Analysis of the Twittersphere
Page 4: Using Clojure for Sentiment Analysis of the Twittersphere

Leiningen Versus the Ants!

Clojure Versus Java!

FP Versus OOP

Page 5: Using Clojure for Sentiment Analysis of the Twittersphere

Leiningen Versus the Ants!

Clojure Versus Java!

FP Versus OOP

Apache Ant

Page 6: Using Clojure for Sentiment Analysis of the Twittersphere

Leiningen Versus the Ants

Clojure Versus Java!

FP Versus OOP

Apache Ant

Page 7: Using Clojure for Sentiment Analysis of the Twittersphere

Leiningen Versus the Ants

Clojure Versus Java

Functional Versus Object Oriented

Apache Ant

Page 8: Using Clojure for Sentiment Analysis of the Twittersphere

“You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.”

Joe Armstrong - inventor of Erlang

Page 9: Using Clojure for Sentiment Analysis of the Twittersphere

“Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a

framework. Just a function.”John Carmack - Lead on Doom, Quake, Rage

Page 10: Using Clojure for Sentiment Analysis of the Twittersphere
Page 11: Using Clojure for Sentiment Analysis of the Twittersphere

Blood aches pain sick shivers spasm vomit dizzy fainting colic and in a coma!

1 FAVORITE

Page 12: Using Clojure for Sentiment Analysis of the Twittersphere

Blood aches pain sick shivers spasm vomit dizzy fainting colic and in a coma!

1 FAVORITE

Scores HIGH for flu symptoms

Page 13: Using Clojure for Sentiment Analysis of the Twittersphere

Blood aches pain sick shivers spasm vomit dizzy fainting colic and in a coma!

1 FAVORITE

Who is Catalina Rubottom?

Page 14: Using Clojure for Sentiment Analysis of the Twittersphere

Blood aches pain sick shivers spasm vomit dizzy fainting colic and in a coma!

1 FAVORITE

HDFS/Hadoop

Mongo/Aggregation

Mongo/MapReduce

Postgres

30 million geo-tagged tweets sent from UK

Page 15: Using Clojure for Sentiment Analysis of the Twittersphere

How can we do fast, real time analytics of

social media?

Page 16: Using Clojure for Sentiment Analysis of the Twittersphere

Store this!

Not this!

Page 17: Using Clojure for Sentiment Analysis of the Twittersphere

WARNING!You’re about to see real Clojure code!

Page 18: Using Clojure for Sentiment Analysis of the Twittersphere

increment 1)(

Page 19: Using Clojure for Sentiment Analysis of the Twittersphere

increment 1)(

Page 20: Using Clojure for Sentiment Analysis of the Twittersphere

increment 1)(

Page 21: Using Clojure for Sentiment Analysis of the Twittersphere

Congratulations - you’re now fully qualified!

increment 1)(

Page 22: Using Clojure for Sentiment Analysis of the Twittersphere

ptaoussanis/carmine

Page 23: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as car]) !!(defn create-tweet-id [] (first (wcar* (car/incr "global:tweet.id")))) !!(defn set-values [sentiment location created-at] (let [tweed-id (create-tweet-id)] (wcar* (car/setbit sentiment tweet-id 1) (car/setbit location tweet-id 1) (car/setbit created-at tweet-id 1))))

Page 24: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as car]) !!(defn create-tweet-id [] (first (wcar* (car/incr "global:tweet.id")))) !!(defn set-values [sentiment location created-at] (let [tweed-id (create-tweet-id)] (wcar* (car/setbit sentiment tweet-id 1) (car/setbit location tweet-id 1) (car/setbit created-at tweet-id 1))))

Page 25: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as car]) !!(defn create-tweet-id [] (first (wcar* (car/incr "global:tweet.id")))) !!(defn set-values [sentiment location created-at] (let [tweed-id (create-tweet-id)] (wcar* (car/setbit sentiment tweet-id 1) (car/setbit location tweet-id 1) (car/setbit created-at tweet-id 1))))

Page 26: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as car]) !!(defn create-tweet-id [] (first (wcar* (car/incr "global:tweet.id")))) !!(defn set-values [sentiment location created-at] (let [tweed-id (create-tweet-id)] (wcar* (car/setbit sentiment tweet-id 1) (car/setbit location tweet-id 1) (car/setbit created-at tweet-id 1))))

Page 27: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as car]) !!(defn create-tweet-id [] (first (wcar* (car/incr "global:tweet.id")))) !!(defn set-values [sentiment location created-at] (let [tweed-id (create-tweet-id)] (wcar* (car/setbit sentiment tweet-id 1) (car/setbit location tweet-id 1) (car/setbit created-at tweet-id 1))))

find value for keyfind bit of index

set bit to 1

Page 28: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar* (car/bitcount "SCOTLAND") (car/bitcount "JOVIALITY") (car/bitcount "26062014114532"))

Page 29: Using Clojure for Sentiment Analysis of the Twittersphere

ENG

SCT

WAL

NIR

valuekey

Page 30: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 1

SCT 0

WAL 0

NIR 0

(car/setbit “ENG” 0 1)

tweet-idkey

valuekey

Page 31: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 1

SCT 1 0

WAL 0 0

NIR 0 0

(car/setbit “SCT” 1 1)

tweet-idkey

valuekey

Page 32: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 1 0 1

SCT 0 1 0

WAL 0 0 0

NIR 0 0 0

(car/setbit “ENG” 2 1)

tweet-idkey

valuekey

Page 33: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

WAL 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0

NIR 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0

(car/setbit “SCT” 15 1)

tweet-idkey

valuekey

Page 34: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

WAL 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0

NIR 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0

(car/bitcount "ENG")

8

valuekey

Page 35: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

WAL 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0

NIR 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0

(car/bitcount "SCT")

84

valuekey

Page 36: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

WAL 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0

NIR 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0

(car/bitcount "WAL")

843

valuekey

Page 37: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

WAL 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0

NIR 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0

(car/bitcount "NIR")

8431

valuekey

Page 38: Using Clojure for Sentiment Analysis of the Twittersphere

JOVIAL

SHY

HOSTILE

FATIGUE

valuekey

Page 39: Using Clojure for Sentiment Analysis of the Twittersphere

JOVIAL 1

SHY 0

HOSTILE 0

FATIGUE 0

(car/setbit “JOVIAL” 0 1)

tweet-idkey

valuekey

Page 40: Using Clojure for Sentiment Analysis of the Twittersphere

JOVIAL 0 1

SHY 0 0

HOSTILE 1 0

FATIGUE 0 0

(car/setbit “HOSTILE” 1 1)

tweet-idkey

valuekey

Page 41: Using Clojure for Sentiment Analysis of the Twittersphere

JOVIAL 0 0 1

SHY 1 0 0

HOSTILE 0 1 0

FATIGUE 0 0 0

(car/setbit “SHY” 2 1)

tweet-idkey

valuekey

Page 42: Using Clojure for Sentiment Analysis of the Twittersphere

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

SHY 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0

FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

(car/setbit “JOVIAL” 15 1)

tweet-idkey

valuekey

Page 43: Using Clojure for Sentiment Analysis of the Twittersphere

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

SHY 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0

FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

(car/bitcount [*])

8134

valuekey

Page 44: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

(car/expire “ENGLAND&JOVIALITY" 10)

(car/bitcount “ENGLAND&JOVIALITY"))

How many people in England are Happy about the referendum result?

Page 45: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

(car/expire “ENGLAND&JOVIALITY" 10)

(car/bitcount “ENGLAND&JOVIALITY"))

How many people in England are Happy about the referendum result?

Page 46: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

(car/expire “ENGLAND&JOVIALITY" 10)

(car/bitcount “ENGLAND&JOVIALITY"))

How many people in England are Happy about the referendum result?

Page 47: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

(car/expire “ENGLAND&JOVIALITY" 10)

(car/bitcount “ENGLAND&JOVIALITY"))

How many people in England are Happy about the referendum result?

Page 48: Using Clojure for Sentiment Analysis of the Twittersphere

How many people in England are Happy about the referendum result?

Page 49: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

How many people in England are Happy about the referendum result?

Page 50: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

How many people in England are Happy about the referendum result?

Page 51: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

1

AND

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

How many people in England are Happy about the referendum result?

Page 52: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

0 1

AND

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

How many people in England are Happy about the referendum result?

Page 53: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

0 0 1

AND

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

How many people in England are Happy about the referendum result?

Page 54: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1

AND

(car/bitop "AND" “ENGLAND&JOVIALITY" "ENGLAND" "JOVIALITY")

How many people in England are Happy about the referendum result?

Page 55: Using Clojure for Sentiment Analysis of the Twittersphere

ENG 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1

JOVIAL 1 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1

0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1

(car/bitcount “ENGLAND&JOVIALITY")

4

How many people in England are Happy about the referendum result?

Page 56: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "OR" "FATIGUE|HOSTILITY" "FATIGUE" “HOSTILITY")

(car/expire "FATIGUE|HOSTILITY" 10)

(car/bitop "AND" "SCOTLAND&(FATIGUE|HOSTILITY)"

"SCOTLAND" "FATIGUE|HOSTILITY")

(car/expire "SCOTLAND&(FATIGUE|HOSTILITY)" 10)

(car/bitcount "SCOTLAND&(FATIGUE|HOSTILITY)"))

How many people in Scotland are Tired and Grumpy after the referendum?

Page 57: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "OR" "FATIGUE|HOSTILITY" "FATIGUE" “HOSTILITY")

(car/expire "FATIGUE|HOSTILITY" 10)

(car/bitop "AND" "SCOTLAND&(FATIGUE|HOSTILITY)"

"SCOTLAND" "FATIGUE|HOSTILITY")

(car/expire "SCOTLAND&(FATIGUE|HOSTILITY)" 10)

(car/bitcount "SCOTLAND&(FATIGUE|HOSTILITY)"))

How many people in Scotland are Tired and Grumpy after the referendum?

Page 58: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "OR" "FATIGUE|HOSTILITY" "FATIGUE" “HOSTILITY")

(car/expire "FATIGUE|HOSTILITY" 10)

(car/bitop "AND" "SCOTLAND&(FATIGUE|HOSTILITY)"

"SCOTLAND" "FATIGUE|HOSTILITY")

(car/expire "SCOTLAND&(FATIGUE|HOSTILITY)" 10)

(car/bitcount "SCOTLAND&(FATIGUE|HOSTILITY)"))

How many people in Scotland are Tired and Grumpy after the referendum?

Page 59: Using Clojure for Sentiment Analysis of the Twittersphere

(wcar*

(car/bitop "OR" "FATIGUE|HOSTILITY" "FATIGUE" “HOSTILITY")

(car/expire "FATIGUE|HOSTILITY" 10)

(car/bitop "AND" "SCOTLAND&(FATIGUE|HOSTILITY)"

"SCOTLAND" "FATIGUE|HOSTILITY")

(car/expire "SCOTLAND&(FATIGUE|HOSTILITY)" 10)

(car/bitcount "SCOTLAND&(FATIGUE|HOSTILITY)"))

How many people in Scotland are Tired and Grumpy after the referendum?

Page 60: Using Clojure for Sentiment Analysis of the Twittersphere

How many people in Scotland are Tired and Grumpy after the referendum?

Page 61: Using Clojure for Sentiment Analysis of the Twittersphere

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0

How many people in Scotland are Tired and Grumpy after the referendum?

Page 62: Using Clojure for Sentiment Analysis of the Twittersphere

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

How many people in Scotland are Tired and Grumpy after the referendum?

Page 63: Using Clojure for Sentiment Analysis of the Twittersphere

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

BOTH

OR

How many people in Scotland are Tired and Grumpy after the referendum?

Page 64: Using Clojure for Sentiment Analysis of the Twittersphere

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0

OR

How many people in Scotland are Tired and Grumpy after the referendum?

Page 65: Using Clojure for Sentiment Analysis of the Twittersphere

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0

OR

How many people in Scotland are Tired and Grumpy after the referendum?

Page 66: Using Clojure for Sentiment Analysis of the Twittersphere

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0

How many people in Scotland are Tired and Grumpy after the referendum?

Page 67: Using Clojure for Sentiment Analysis of the Twittersphere

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0

AND

How many people in Scotland are Tired and Grumpy after the referendum?

Page 68: Using Clojure for Sentiment Analysis of the Twittersphere

SCT 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 00 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0

HOSTILE 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0FATIGUE 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0

BOTH 0 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0

2

How many people in Scotland are Tired and Grumpy after the referendum?

Page 69: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

Page 70: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

adamwynne/twitter-api

Page 71: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

clojurewerkz/meltdown

LMAX-Exchange/disruptor

Page 72: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

dakrone/clojure-opennlp

Page 73: Using Clojure for Sentiment Analysis of the Twittersphere

“I’m loving #XConfMCR! ”

Page 74: Using Clojure for Sentiment Analysis of the Twittersphere

Positive Affect: enthusiastic, active, alert !

Negative Affect: subjective distress !

Emerged as distinctive, orthogonal dimensions

Page 75: Using Clojure for Sentiment Analysis of the Twittersphere

PANAS

1

23

4

51

3153

2335345221

Page 76: Using Clojure for Sentiment Analysis of the Twittersphere

PANAS

1

23

4

51

3153

2335345221

1 3 5 9 10 12 14 16 17 19

2 4 6 7 8 11 13 15 18 20

Page 77: Using Clojure for Sentiment Analysis of the Twittersphere

PANAS

1

2345

1

31

53

233534

5 22 1

1 3 5 9 10 12 14 16 17 19

2 4 6 7 8 11 13 15 18 20

39 19

positive affect! negative affect

Page 78: Using Clojure for Sentiment Analysis of the Twittersphere

PANAS-xGeneral Dimension Scales!Negative Affect (10) Positive Affect (10)

Basic Positive Emotions Scales!Joviality (8) Self-assurance (6) Attentiveness (4)

Basic Negative Emotions Scales!Fear (6) Hostility (6) Guilt (6) Sadness (5)

Other Affective States!Shyness (4) Fatigue (4) Serenity (3) Surprise (3)

Page 79: Using Clojure for Sentiment Analysis of the Twittersphere

PANAS-t

Accounts for bias on social media!

Outlines sanitisation

Validate against 10 real events

Page 81: Using Clojure for Sentiment Analysis of the Twittersphere

SHYNESS FATIGUE

SERENITY SURPRISE

FEAR HOSTILITY

GUILT SADNESS

JOVIALITY SELF ASSURANCE ATTENTIVENESS

We have sentiment key

s!

Page 82: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

mbostock/d3

Page 83: Using Clojure for Sentiment Analysis of the Twittersphere

[-75.14310264, 40.05701649]

Page 84: Using Clojure for Sentiment Analysis of the Twittersphere

Reverse Geocoding Issues• Don’t want external services

• Don’t want heavy IO

• Don’t want round trips to the database

• Accuracy not too much of a concern

Page 85: Using Clojure for Sentiment Analysis of the Twittersphere
Page 86: Using Clojure for Sentiment Analysis of the Twittersphere
Page 87: Using Clojure for Sentiment Analysis of the Twittersphere

Equirectangular Projection

Page 88: Using Clojure for Sentiment Analysis of the Twittersphere

Courtesy of Eric Gaba (Wikimedia Commons User: Sting)

Page 89: Using Clojure for Sentiment Analysis of the Twittersphere

x = λcosφ1 y = φ

Tissot's indicatrix of deformation

Courtesy of Eric Gaba (Wikimedia Commons User: Sting)

Page 90: Using Clojure for Sentiment Analysis of the Twittersphere
Page 91: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

Page 92: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

[lon, lat] = [55.86140, -4.26477]

[x, y] = [329, 601]

[x, y] = = Scotland!

Page 93: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

[lon, lat] = [55.86140, -4.26477]

[x, y] = [329, 601]

[x, y] = = Scotland!

Page 94: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

[lon, lat] = [55.86140, -4.26477]

[x, y] = [329, 601]

[x, y] = = Scotland!

Page 95: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

[lon, lat] = [55.86140, -4.26477]

[x, y] = [329, 601]

[x, y] = = Scotland!

Page 96: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

[lon, lat] = [55.86140, -4.26477]

[x, y] = [329, 601]

[x, y] = = Scotland!

Page 97: Using Clojure for Sentiment Analysis of the Twittersphere

x (px)

y (px)

[lon, lat] = [55.86140, -4.26477]

[x, y] = [329, 601]

[x, y] = = Scotland!

Page 98: Using Clojure for Sentiment Analysis of the Twittersphere

Server side! (JavaFX)

Mike Bostock & Nick Rabinowitz

Page 99: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [hiccup.page :as hiccup]) (:import (javafx.scene.web WebView)) !(def scripts ["uk-data.js" "topojson.v1.min.js" "d3.v3.min.js" "geocoder.js"]) !(defn create-browser [html] (-> WebView. .getEngine (.loadContent html))) !(defn build-page [script-paths] (hiccup/html5 [:head (for [path script-paths] [:script (slurp (io/resource path))])])) !(defn coordinates->name [longitude latitude] (let [browser (-> scripts build-page create-browser)] (.executeScript browser (str "geo.decode([" longitude "," latitude "])"))))

JavaFX

Page 100: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [hiccup.page :as hiccup]) (:import (javafx.scene.web WebView)) !(def scripts ["uk-data.js" "topojson.v1.min.js" "d3.v3.min.js" "geocoder.js"]) !(defn create-browser [html] (-> WebView. .getEngine (.loadContent html))) !(defn build-page [script-paths] (hiccup/html5 [:head (for [path script-paths] [:script (slurp (io/resource path))])])) !(defn coordinates->name [longitude latitude] (let [browser (-> scripts build-page create-browser)] (.executeScript browser (str "geo.decode([" longitude "," latitude "])"))))

JavaFX

Page 101: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [hiccup.page :as hiccup]) (:import (javafx.scene.web WebView)) !(def scripts ["uk-data.js" "topojson.v1.min.js" "d3.v3.min.js" "geocoder.js"]) !(defn create-browser [html] (-> WebView. .getEngine (.loadContent html))) !(defn build-page [script-paths] (hiccup/html5 [:head (for [path script-paths] [:script (slurp (io/resource path))])])) !(defn coordinates->name [longitude latitude] (let [browser (-> scripts build-page create-browser)] (.executeScript browser (str "geo.decode([" longitude "," latitude "])"))))

JavaFX

Page 102: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [hiccup.page :as hiccup]) (:import (javafx.scene.web WebView)) !(def scripts ["uk-data.js" "topojson.v1.min.js" "d3.v3.min.js" "geocoder.js"]) !(defn create-browser [html] (-> WebView. .getEngine (.loadContent html))) !(defn build-page [script-paths] (hiccup/html5 [:head (for [path script-paths] [:script (slurp (io/resource path))])])) !(defn coordinates->name [longitude latitude] (let [browser (-> scripts build-page create-browser)] (.executeScript browser (str "geo.decode([" longitude "," latitude "])"))))

JavaFX

Page 103: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [hiccup.page :as hiccup]) (:import (javafx.scene.web WebView)) !(def scripts ["uk-data.js" "topojson.v1.min.js" "d3.v3.min.js" "geocoder.js"]) !(defn create-browser [html] (-> WebView. .getEngine (.loadContent html))) !(defn build-page [script-paths] (hiccup/html5 [:head (for [path script-paths] [:script (slurp (io/resource path))])])) !(defn coordinates->name [longitude latitude] (let [browser (-> scripts build-page create-browser)] (.executeScript browser (str "geo.decode([" longitude "," latitude "])"))))

Stuart Sierras

Component lib!!

JavaFX

Page 104: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

KirinDave/clj-time

Page 105: Using Clojure for Sentiment Analysis of the Twittersphere

“Thu Jun 26 14:35:57 +0000 2014”

over 86 thousand seconds in a dayover 31 million seconds in a year

Page 106: Using Clojure for Sentiment Analysis of the Twittersphere
Page 107: Using Clojure for Sentiment Analysis of the Twittersphere
Page 108: Using Clojure for Sentiment Analysis of the Twittersphere

mm:260620141435

Page 109: Using Clojure for Sentiment Analysis of the Twittersphere

HH:260620141400

Page 110: Using Clojure for Sentiment Analysis of the Twittersphere

Monday Tuesday Wednesday Thursday Friday Saturday Sunday

1

2 3 4 5 6 7 8

9 10 11 12 13 14 15

16 17 18 19 20 21 22

23 24 25 27 28 29

30 31

dd:260620140000

Page 111: Using Clojure for Sentiment Analysis of the Twittersphere

JAN FEB MAR APR

MAY JUL AUG

SEP OCT NOV DEC

MM:010620140000

Page 112: Using Clojure for Sentiment Analysis of the Twittersphere

2013

2015

yy:010120140000

Page 113: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [clj-time.format :as time]) !

!

(def input-formatter "EE MMM d HH:mm:ss Z yyyy") (def formats { "mm:" "ddMMyyHHmm" "HH:" "ddMMyyHH00" ... }) !

!

(defn create-key [date [prefix formatter]] (let [out-date (time/unparse formatter date)] (str prefix out-date))) !

!

(defn date->keys [created_at] (let [date (time/parse input-formatter created_at)] (map #(create-key date %) formats)))

Page 114: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [clj-time.format :as time]) !

!

(def input-formatter "EE MMM d HH:mm:ss Z yyyy") (def formats { "mm:" "ddMMyyHHmm" "HH:" "ddMMyyHH00" ... }) !

!

(defn create-key [date [prefix formatter]] (let [out-date (time/unparse formatter date)] (str prefix out-date))) !

!

(defn date->keys [created_at] (let [date (time/parse input-formatter created_at)] (map #(create-key date %) formats)))

Page 115: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [clj-time.format :as time]) !

!

(def input-formatter "EE MMM d HH:mm:ss Z yyyy") (def formats { "mm:" "ddMMyyHHmm" "HH:" "ddMMyyHH00" ... }) !

!

(defn create-key [date [prefix formatter]] (let [out-date (time/unparse formatter date)] (str prefix out-date))) !

!

(defn date->keys [created_at] (let [date (time/parse input-formatter created_at)] (map #(create-key date %) formats)))

Page 116: Using Clojure for Sentiment Analysis of the Twittersphere

RINGSyncing

Journaling

Business logic

What

Where

When

Mem

ory

Web

API

Incoming Data

ptaoussanis/carmine

Page 117: Using Clojure for Sentiment Analysis of the Twittersphere

SENTIMENT !

LOCATION !

mm:date-time HH:date-time dd:date-time MM:date-time yy:date-time

We have 11 keys in total!

What

Where

When

Page 118: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as redis]) !

!

(defn create-tweet-id [] (redis/incr "global:tweet.id")) !

!

(defn set-bits [data-keys tweet-id] (doseq [data-key data-keys] (redis/setbit data-key tweet-id 1))) !

!

(defn data->analytics [data-keys] (let [tweet-id (create-tweet-id)] (set-bits data-keys tweet-id)))

Page 119: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as redis]) !

!

(defn create-tweet-id [] (redis/incr "global:tweet.id")) !

!

(defn set-bits [data-keys tweet-id] (doseq [data-key data-keys] (redis/setbit data-key tweet-id 1))) !

!

(defn data->analytics [data-keys] (let [tweet-id (create-tweet-id)] (set-bits data-keys tweet-id)))

Page 120: Using Clojure for Sentiment Analysis of the Twittersphere

(:require [taoensso.carmine :as redis]) !

!

(defn create-tweet-id [] (redis/incr "global:tweet.id")) !

!

(defn set-bits [data-keys tweet-id] (doseq [data-key data-keys] (redis/setbit data-key tweet-id 1))) !

!

(defn data->analytics [data-keys] (let [tweet-id (create-tweet-id)] (set-bits data-keys tweet-id)))

Page 121: Using Clojure for Sentiment Analysis of the Twittersphere

{ 'query-type': 'count', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

weavejester/compojure

JSON query

Page 122: Using Clojure for Sentiment Analysis of the Twittersphere

{ 'query-type': 'count', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

weavejester/compojure

JSON query

/api?_query={json}

Page 123: Using Clojure for Sentiment Analysis of the Twittersphere

(defmulti execute :query-type) !!(defmethod execute “count" [] … logic here) !!(defmethod execute “p-affect“ [] … logic here) !!(defmethod execute “n-affect“ [] … logic here)

{ 'query-type': 'count', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

weavejester/compojure

JSON query

/api?_query={json}

Page 124: Using Clojure for Sentiment Analysis of the Twittersphere

(defmulti execute :query-type) !!(defmethod execute “count" [] … logic here) !!(defmethod execute “p-affect“ [] … logic here) !!(defmethod execute “n-affect“ [] … logic here)

{ 'query-type': 'count', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

weavejester/compojure

JSON query

/api?_query={json}

Page 125: Using Clojure for Sentiment Analysis of the Twittersphere

(defmulti execute :query-type) !!(defmethod execute “count" [] … logic here) !!(defmethod execute “p-affect“ [] … logic here) !!(defmethod execute “n-affect“ [] … logic here)

weavejester/compojure

JSON query

/api?_query={json}

{ 'query-type': 'count', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

Page 126: Using Clojure for Sentiment Analysis of the Twittersphere

(defmulti execute :query-type) !!(defmethod execute “count" [] … logic here) !!(defmethod execute “p-affect“ [] … logic here) !!(defmethod execute “n-affect“ [] … logic here)

weavejester/compojure

JSON query

/api?_query={json}

{ 'query-type': ‘p-affect', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

Page 127: Using Clojure for Sentiment Analysis of the Twittersphere

(defmulti execute :query-type) !!(defmethod execute “count" [] … logic here) !!(defmethod execute “p-affect“ [] … logic here) !!(defmethod execute “n-affect“ [] … logic here)

weavejester/compojure

JSON query

/api?_query={json}

{ 'query-type': ‘p-affect', 'params': { 'sentiments': [ 'FATIGUE', 'HOSTILITY' ], 'locations': [ 'SCT' ] } }

Page 128: Using Clojure for Sentiment Analysis of the Twittersphere