Cheuk Ting Ho
Developer advocate / Data Scientist - support open-source and building the community.
Cheuk Ting Ho
Grab the slides: http://bit.ly/PyConLimerickGraphViz
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 (with Python)
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"),
)
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?
Python >= 3.6 ✅
TerminusDB installed ✅ (v1.1.7)
import woqlclient.woqlClient as woql
server_url = "http://localhost:6363"
dbId = "mydb"
key = "root"
dburl = server_url + "/mydb"
client = woql.WOQLClient()
client.connect(server_url, key)
client.createDatabase(dbId, "Dublin Council Graph")
Example Script is on GitHub:
def create_schema(client):
schema = WOQLQuery().when(True).woql_and(
WOQLQuery().doctype("Party").
label("Party").
description("Political Party"),
WOQLQuery().doctype("Representative").
label("Representative").
description("An elected member Dublin city council").
property("member_of", "Party").
label("Member of").cardinality(1),
WOQLQuery().doctype("Similarity").
label("Similarity").
property("similarity", "decimal").
label("Similarity").
property("similar_to", "Representative").
label("Similar To").cardinality(2)
)
return schema.execute(client)
Example Script is on GitHub:
def get_csv_variables(url):
csv = WOQLQuery().get(
WOQLQuery().woql_as("councillor_a", "v:Rep_A").
woql_as("councillor_b", "v:Rep_B").
woql_as("party_a", "v:Party_A").
woql_as("party_b", "v:Party_B").
woql_as("distance", "v:Distance")
).remote(url)
return csv
def get_wrangles():
wrangles = [
WOQLQuery().idgen("doc:Party", ["v:Party_A"], "v:Party_A_ID"),
WOQLQuery().idgen("doc:Party", ["v:Party_B"], "v:Party_B_ID"),
WOQLQuery().idgen("doc:Representative", ["v:Rep_A"], "v:Rep_A_ID"),
WOQLQuery().idgen("doc:Representative", ["v:Rep_B"], "v:Rep_B_ID"),
WOQLQuery().typecast("v:Distance", "xsd:decimal", "v:Similarity"),
WOQLQuery().idgen("doc:Similarity", ["v:Rep_A", "v:Rep_B"], "v:Rel_ID"),
WOQLQuery().concat("v:Rep_A similarity v:Distance to v:Rep_B", "v:Rel_Label")
]
return wrangles
Example Script is on GitHub:
def get_inserts():
inserts = WOQLQuery().woql_and(
WOQLQuery().insert("v:Party_A_ID", "Party").label("v:Party_A"),
WOQLQuery().insert("v:Party_B_ID", "Party").label("v:Party_B"),
WOQLQuery().insert("v:Rep_A_ID", "Representative").label("v:Rep_A").
property("member_of", "v:Party_A_ID"),
WOQLQuery().insert("v:Rep_B_ID", "Representative").label("v:Rep_B").
property("member_of", "v:Party_B_ID"),
WOQLQuery().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")
)
return inserts
def load_csvs(client, csvs):
for key, url in csvs.items():
csv = get_csv_variables(url)
wrangles = get_wrangles()
inputs = WOQLQuery().woql_and(csv, *wrangles)
inserts = get_inserts()
answer = WOQLQuery().when(inputs, inserts)
answer.execute(client)
Example Script is on GitHub:
/*******************
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.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])
Example Script is on GitHub:
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)
Originality, Technical correctness, Informative
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
Meetup:
DataOps and my first TerminusDB knowledge graph
5th March - Dogpatch Labs
To get the newest update👍:
Follow us on Twitter: @TerminusDB
Website: https://terminusdb.com/
Join the community:
By Cheuk Ting Ho
Graph Visulization on Voting Data
Developer advocate / Data Scientist - support open-source and building the community.