Are you supporting the right politician?

Graph Visualization of Voting Data

Cheuk Ting Ho

Grab the slides:
http://bit.ly/CivicLabGraphViz

About me

Co-organizer of 

Open Source contribution

Creator of

Volenteer of

Developer Advocate of

Have you ever check what issues that a politician support before you vote?

Or, do you just vote for them because of the party that they are in?

Do you think your Councilor represent you in local issues?

Have you ever check what they vote for in the Dublin Council?

Politics can be complicated...

But data never lies...

(only people who interpete them does)

I gonna teach you how to analyze the voting data

So...
What's a Graph?
And Why?

  • much easier to interpret the model

  • understand how it maps to real world entities compared to the relational example

SELECT Name from TABLE where Person_ID = (SELECT mother from TABLE where Name="John")
SELECT Name from TABLE where Person_ID = (SELECT mother from TABLE WHERE Person_ID = (SELECT mother from TABLE where Name="John"))
WOQL.and(
   WOQL.triple("v:Person", "mother", "v:MotherID"),
   WOQL.triple("v:MotherID", "name", "v:MotherName"),
   WOQL.triple("v:MotherID", "mother", "v:GrandmotherID"),
   WOQL.triple("v:GrandmotherID", "name", "v:GrandmotherName"),
)

Getting
the Data

Install TerminusDB 

Setup Checklist

Do you have TerminusDB installed?

Yes

No

Good to go

Do you have Docker?

Yes

No

Which OS?

Mac / Linux / Window 10 Pro

No

Others

Do you have TerminusDB installed?

Create a Graph DB 

1. Make sure TerminusDB is running

2. http://localhost:6363/console
3. Create a new Database

Create a Schema

WOQL.when(true).and(
        WOQL.doctype("Party")
            .label("Party")
            .description("Political Party"),
        WOQL.doctype("Representative")
            .label("Representative")
            .description("An elected member of the Dublin city council")
            .property("member_of", "Party")
                .label("Member of").cardinality(1),
        WOQL.doctype("Similarity")
            .label("Similarity")
            .property("similarity", "decimal")
                .label("Similarity")
            .property("similar_to", "Representative")
                .label("Similar To").cardinality(2)
  )

Load-in
the Data

let csv = WOQL.get(
        WOQL.as("councillor_a","v:Rep_A")
        .as("councillor_b", "v:Rep_B")
        .as("party_a", "v:Party_A")
        .as("party_b", "v:Party_B")
        .as("distance", "v:Distance")
    ).remote("https://terminusdb.com/t/data/council/weighted_similarity.csv");
  
let wrangles = [
         WOQL.idgen("doc:Party", ["v:Party_A"], "v:Party_A_ID"),
         WOQL.idgen("doc:Party", ["v:Party_B"], "v:Party_B_ID"),
         WOQL.idgen("doc:Representative", ["v:Rep_A"], "v:Rep_A_ID"),
         WOQL.idgen("doc:Representative", ["v:Rep_B"], "v:Rep_B_ID"),
         WOQL.typecast("v:Distance", "xsd:decimal", "v:Similarity"),
         WOQL.idgen("doc:Similarity", ["v:Rep_A", "v:Rep_B"], "v:Rel_ID"),
         WOQL.concat("v:Rep_A similarity v:Distance to v:Rep_B", "v:Rel_Label")
     ];

let inputs = WOQL.and(csv, ...wrangles);
let inserts = WOQL.and(
        WOQL.insert("v:Party_A_ID", "Party")
            .label("v:Party_A"),
        WOQL.insert("v:Party_B_ID", "Party")
            .label("v:Party_B"),
        WOQL.insert("v:Rep_A_ID", "Representative")
            .label("v:Rep_A")
            .property("member_of", "v:Party_A_ID"),
        WOQL.insert("v:Rep_B_ID", "Representative")
            .label("v:Rep_B")
            .property("member_of", "v:Party_B_ID"),
        WOQL.insert("v:Rel_ID", "Similarity")
            .label("v:Rel_Label")
            .property("similar_to", "v:Rep_A_ID")
            .property("similar_to", "v:Rep_B_ID")
            .property("similarity", "v:Similarity")
    );
  
WOQL.when(inputs, inserts)

Making Sense of the Data

/*******************
 Query Script
********************/

WOQL.limit(1000).and(
    WOQL.triple("v:Subject","similar_to","v:Value"),
    WOQL.triple("v:Subject","similar_to","v:Value2"),
    WOQL.triple("v:Subject","similarity","v:Similarity"),
    WOQL.triple("v:Value","member_of","v:Party"),
    WOQL.triple("v:Value2","member_of","v:Party2"),
    WOQL.not().eq("v:Value","v:Value2"),
    WOQL.opt().triple("v:Value2","label","v:Lab2"),
    WOQL.opt().triple("v:Value","label","v:Lab1"),
    WOQL.eval(WOQL.divide(1, WOQL.exp("v:Similarity", 4)), "v:Distance")
)

/***************************************
 View Script for Dublin City Council
****************************************/

view = View.graph();
view.height(800);
view.node("v:Subject", "v:Lab2", "v:Lab1", "v:Party2", "v:Party", "v:Similarity", "v:Distance").hidden(true)
view.node("v:Similarity").hidden(true)
view.edge("v:Value", "v:Value2").distance("v:Distance").text("v:Distance").weight(0.04)
view.node("v:Value").text("v:Lab1").icon({ label: true})
view.node("v:Value2").text("v:Lab2").icon({ label: true})
view.node("v:Value", "v:Value2").charge(-4999).collisionRadius(30)
view.node("v:Value").v("v:Party").in("doc:PartySolidarity").color([5, 25, 22])
view.node("v:Value2").v("v:Party2").in("doc:PartySolidarity").color([5, 25, 22])
view.node("v:Value").v("v:Party").in("doc:PartySocial%20Democrats").color([25, 25, 225])
view.node("v:Value2").v("v:Party2").in("doc:PartySocial%20Democrats").color([25, 25, 225])
view.node("v:Value").v("v:Party").in("doc:PartySinn%20F%C3%A9in").color([25, 225, 25])
view.node("v:Value2").v("v:Party2").in("doc:PartySinn%20F%C3%A9in").color([25, 225, 25])
view.node("v:Value").v("v:Party").in("doc:PartyLabour%20Party").color([255, 0, 0])
view.node("v:Value2").v("v:Party2").in("doc:PartyLabour%20Party").color([255, 0, 0])
view.node("v:Value2").v("v:Party2").in("doc:PartyFine%20Gael").color([0, 0, 255])
view.node("v:Value").v("v:Party").in("doc:PartyFine%20Gael").color([0, 0, 255])
view.node("v:Value").v("v:Party").in("doc:PartyFianna%20F%C3%A1il").color([100, 200, 100])
view.node("v:Value2").v("v:Party2").in("doc:PartyFianna%20F%C3%A1il").color([100, 200, 100])
view.node("v:Value").v("v:Party").in("doc:PartyGreen%20Party").color([25, 225, 125])
view.node("v:Value2").v("v:Party2").in("doc:PartyGreen%20Party").color([225, 225, 125])
view.node("v:Value").v("v:Party").in("doc:PartyIndependent").color([25, 25, 25])
view.node("v:Value2").v("v:Party2").in("doc:PartyIndependent").color([25, 25, 25])
view.node("v:Value").v("v:Party").in("doc:PartyPeople%20Before%20Profit").color([225, 25, 25])
view.node("v:Value2").v("v:Party2").in("doc:PartyPeople%20Before%20Profit").color([225, 25, 25])
view.node("v:Value").v("v:Party").in("doc:PartyWorkers'%20Party").color([225, 225, 225])
view.node("v:Value2").v("v:Party2").in("doc:PartyWorkers'%20Party").color([225, 225, 225])

So How About UK Parliament

You time to shine
🌟

And win some prices

Competition deadline: 17th Mar 2020 (St. Patrick's Day!)

Team: 1-3 ppl

Format: a Jupyter notebook (.ipynb file) or a blog post

*Submission need to be publicly available (e.g. host on GitHub or published blog post)

 

Show us any interesting findings with the UK Parliament data using a similar method. Be creative!

Originality, Technical correctness, Informative

Prices:

1. £100 amazon gift card for the winning team

2. each team member will get a TerminusDB swag bundle

(include Hoodie Jacket, E-Coffee Mug and much more)

 

Winner will also be invited to speak at our meetup in Dublin
(and/or London!)

 

Submittion/ Questions: luke@datachemist.com
Name(s), contact email(s), link to submittion

Webinar:
Anatomy of a Knowledge Graph
10th March - 5pmCET

 

To get the newest update👍:

Follow us on Twitter: @TerminusDB

Website: https://terminusdb.com/

Join the community:

https://community.terminusdb.com/

Civic Lab Summit - Are you supporting the right politician?

By Cheuk Ting Ho

Civic Lab Summit - Are you supporting the right politician?

Graph Visulization on Voting Data

  • 488
Loading comments...

More from Cheuk Ting Ho