Kandidatų duomenų analizė remiasi A. Tapino pasiūlytu metodu.
Rinkimų dieną reikės išsirinkti:
Vienmandatės apygardos kandidatą.
Daugiamandatės apygardos partiją (sąrašą).
Surašyti 5 pirmumo balsus iš pasirinktos partijos.
Tam, kad geriau suprastumėte partijų sudėtį, žemiau rasite visų vienmandačių apygardų ir daugiamandačių partijų sudėčių vizualizaciją sudarytą pagal A. Tapino pasiūlytus vertinimo kriterijus.
Duomenys analizei surinkti iš vrk.lt svetainės.
Jei jus domina, tik rezultatai, galite peršokti tiesiai prie rezultatų dalies. Jei taip pat domina kaip buvo surinkti duomenys ir kaip atlikti skaičiavimai, galite skaityti nuo pradžių.
Jei pastebėjote klaidų, praneškite https://gist.github.com/sirex/e63f65fed33c81a45f6f9dc908afc560 komentaruose.
Perbraukti punktai nebuvo įtraukti į vertinimą, dėl sunkiai prieinamų duomenų.
Vyriausioji rinkimų komisija nepateikia „žalių“ duomenų apie kandidatus, todėl juos tenka susirinkti sunkiuoju būdu iš vrk.lt svetainės. Atliekant analizę, duomenų surinkimas pareikalavo apie 80% viso laiko.
Kadangi duomenys iš vrk.lt svetainės jau surinkti, kad kitiems nereikėtų to kartoti, visus „žalius“ duomenis galite rasti adresu http://atviriduomenys.lt/data/vrk/rinkimai/2016/
%matplotlib inline
import databot
import urllib.parse
import base64
import imghdr
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import datetime
import re
import textwrap
from IPython.display import display, HTML
mpl.rc('font', family='Ubuntu', size=16)
mpl.rc('figure', figsize=(16, 10))
bot = databot.Bot('vrk_kadidatai.db')
table_page = bot.define('kandidatų-lentelės-puslapis')
table = bot.define('kandidatų-lentelė')
questions_page = bot.define('anketos-puslapis')
questions = bot.define('anketa')
degree = bot.define('mokslo-laipsnis')
photo = bot.define('nuotrauka')
experience = bot.define('patirtis')
education = bot.define('išsilavinimas')
profile_links = bot.define('profilio-nuorodos')
bio_page = bot.define('biografijos-puslapis')
bio = bot.define('biografija')
assets_page = bot.define('turto-deklaracijos-puslapis')
assets = bot.define('turto-deklaracijos')
interests_page = bot.define('interesų-deklaracijos-puslapis')
interests = bot.define('interesų-dekraracijos')
campaign_page = bot.define('kampanijos-lėšų-puslapis')
other_page = bot.define('kita-puslapis')
Atsisiunčiame pirmą puslapį su visų kandidatų sąrašu. vrk.lt svetainėje, nuorodos rodomos naršyklėje užkrauna tik puslapio rėmus, o turinys siunčiamas atskirai, JavaScript pagalba, todėl su nuorodomis reikia tam tikro „masažavimo“.
table_page.download('http://vrk.lt/pub/webcontent/kandidatai/lrsKandidataiPilnasSarasasHtml?rnkId=426')
<databot.Pipe[1]: kandidatų-lentelės-puslapis>
Iš pirmo puslapio išsirenkame nuorodas į kandidatų profilius ir duomenis iš kandidatų lentelės.
@databot.func(skipna=True)
def fixlink(link):
url = dict(urllib.parse.parse_qsl(urllib.parse.urlparse(link).query))['srcUrl']
return 'http://vrk.lt/pub/webcontent/' + url
@databot.func()
def vardas(name):
return ' '.join([w for w in name.split() if w[-1].islower()])
@databot.func()
def pavarde(name):
return ' '.join([w for w in name.split() if w[-1].isupper()])
with table_page:
table.select([
'table.partydata tbody tr', (
fixlink('td[1] a@href'), {
'vardas': vardas('td[1] a:text'),
'pavardė': pavarde('td[1] a:text'),
'sąrašas': {
'pavadinimas': 'td[2] a:text?',
'nuoroda': 'td[2] a@href?',
},
'numeris sąraše': 'td[3]:text',
'vienmadatė apygarda': {
'pavadinimas': 'td[5] a:text?',
'nuoroda': 'td[5] a@href?',
},
'iškėlė vienmandatėje': {
'pavadinimas': databot.first('td[6] a:text?', 'td[6]:text'),
'nuoroda': 'td[6] a@href?',
},
}
)
])
kandidatų-lentelės-puslapis -> kandidatų-lentelė: 100%|██████████| 1/1 [00:04<00:00, 4.08s/it]
with table:
questions_page.download()
kandidatų-lentelė -> anketos-puslapis: 100%|██████████| 1415/1415 [02:46<00:00, 9.10it/s]
@databot.func(skipna=True)
def join(value):
return ' '.join(value)
with questions_page:
questions.select([
'body > div[3] > table > tr', (
databot.row.key, {
'klausimas': join(['xpath:./td/text()']),
'atsakymas': 'xpath:./td/b/text()?',
}
)
])
anketos-puslapis -> anketa: 100%|██████████| 1415/1415 [00:26<00:00, 52.53it/s]
with questions_page:
degree.select(databot.row.key, 'xpath://td[contains(text(), "Jei turite, nurodykite pedagoginį vardą, mokslo laipsnį")]/b/text()')
@databot.func(skipna=True)
def decode_photo(value):
return base64.b64decode(value[len('data:;base64,'):])
@databot.func(skipna=True)
def detect_image_type(blob):
return imghdr.what(None, blob)
with questions_page:
photo.clean().reset().select(databot.row.key, {
'body': decode_photo('body > div[1] img@src?'),
'type': detect_image_type(decode_photo('body > div[1] img@src?')),
})
anketos-puslapis -> nuotrauka: 100%|██████████| 1415/1415 [00:17<00:00, 82.98it/s]
with questions_page:
profile_links.clean().reset().select(
databot.row.key, {
'biografija': fixlink('xpath://body/ul[1]/li/a[contains(text(), "Biografija")]/@href'),
'turtas': fixlink('xpath://body/ul[1]/li/a[contains(text(), "Turto ir pajamų")]/@href'),
'interesai': fixlink('xpath://body/ul[1]/li/a[contains(text(), "Privačių interesų")]/@href'),
'kampanija': fixlink('xpath://body/ul[1]/li/a[contains(text(), "Politinės kampanijos")]/@href?'),
'kita': fixlink('xpath://body/ul[1]/li/a[contains(text(), "Kita")]/@href'),
},
)
anketos-puslapis -> profilio-nuorodos: 100%|██████████| 1415/1415 [00:09<00:00, 150.52it/s]
Atsisiunčiame visus kandidato profilio puslapius iš profilio meniu.
with profile_links:
bio_page.download(databot.row.value.biografija)
assets_page.download(databot.row.value.turtas)
interests_page.download(databot.row.value.interesai)
campaign_page.download(databot.row.value.kampanija)
other_page.download(databot.row.value.kita)
profilio-nuorodos -> biografijos-puslapis: 100%|██████████| 1415/1415 [02:24<00:00, 9.72it/s] profilio-nuorodos -> turto-deklaracijos-puslapis: 100%|██████████| 1415/1415 [02:34<00:00, 9.80it/s] profilio-nuorodos -> interesų-deklaracijos-puslapis: 100%|██████████| 1415/1415 [03:04<00:00, 7.65it/s] profilio-nuorodos -> kampanijos-lėšų-puslapis: 100%|██████████| 1415/1415 [01:05<00:00, 21.77it/s] profilio-nuorodos -> kita-puslapis: 100%|██████████| 1415/1415 [02:18<00:00, 10.22it/s]
with questions_page:
experience.select([
'xpath://table[contains(thead/tr/th/text(), "Institucijos pavadinimas, pareigos")]/tr', (
databot.row.key, {
'institucija': split('td[1]:text', 1, ',', 0),
'pareigos': split('td[1]:text', 1, ',', 1),
'laikotarpis': split('td[2]:text', 1, ',', 0),
})
])
anketos-puslapis -> patirtis: 100%|██████████| 1415/1415 [00:09<00:00, 145.74it/s]
with questions_page:
education.select([
'xpath://table[contains(thead/tr/th/text(), "Išsilavinimas")]/tr', (
databot.row.key, {
'išsilavinimas': 'td[1]:text',
'mokymo įstaiga': 'td[2]:text',
'specialybė': 'td[3]:text',
'baigimo metai': 'td[4]:text',
})
])
anketos-puslapis -> išsilavinimas: 100%|██████████| 1415/1415 [00:10<00:00, 139.51it/s]
@databot.func(skipna=True)
def euro(value):
return int(value.replace('Eur', '').strip())
with assets_page:
assets.select(databot.row.key, {
'turtas': euro('xpath://tr[contains(td/text(), "Privalomas registruoti turtas")]/td[2]/b/text()'),
'vertybės': euro('xpath://tr[contains(td/text(), "Vertybiniai popieriai")]/td[2]/b/text()'),
'pinigai': euro('xpath://tr[contains(td/text(), "Piniginės lėšos")]/td[2]/b/text()'),
'suteiktos paskolos': euro('xpath://tr[contains(td/text(), "Suteiktos paskolos")]/td[2]/b/text()'),
'gautos paskolos': euro('xpath://tr[contains(td/text(), "Gautos paskolos")]/td[2]/b/text()'),
})
turto-deklaracijos-puslapis -> turto-deklaracijos: 100%|██████████| 1395/1395 [00:06<00:00, 222.86it/s]
with bio_page:
bio.select(databot.row.key, databot.text('body > div[3]'))
Patikriname ar visi puslapiai sėkmingai atsisiuntė ir ar duomenų išrinkimas praėjo be klaidų.
profilio-nuorodos -> (biografijos-puslapis, kampanijos-lėšų-puslapis
turi klaidų, bet tos klaidos susiję su tuo, kad ne visi kandidatai turi biografijos puslapius ir ne visi asmeniškai administruoja savo kampanijos lėšas, todėl tų puslapių tiesiog nėra.
bot.main(argv=['status'])
id rows source errors left target ========================================================= 1 1 kandidatų-lentelės-puslapis 0 0 kandidatų-lentelė --------------------------------------------------------- 2 1415 kandidatų-lentelė 0 0 anketos-puslapis --------------------------------------------------------- 3 1415 anketos-puslapis 0 0 anketa 0 0 nuotrauka 0 0 profilio-nuorodos 0 0 patirtis 0 0 išsilavinimas 0 0 mokslo-laipsnis --------------------------------------------------------- 4 43014 anketa --------------------------------------------------------- 18 1415 mokslo-laipsnis --------------------------------------------------------- 12 1415 nuotrauka --------------------------------------------------------- 16 1181 patirtis --------------------------------------------------------- 17 1708 išsilavinimas --------------------------------------------------------- 13 1415 profilio-nuorodos 0 0 biografijos-puslapis 20 0 turto-deklaracijos-puslapis 0 0 interesų-deklaracijos-puslapis 742 0 kampanijos-lėšų-puslapis 0 0 kita-puslapis --------------------------------------------------------- 5 1415 biografijos-puslapis 0 0 biografija --------------------------------------------------------- 6 1415 biografija --------------------------------------------------------- 7 1395 turto-deklaracijos-puslapis 3 0 turto-deklaracijos --------------------------------------------------------- 8 1392 turto-deklaracijos --------------------------------------------------------- 9 1415 interesų-deklaracijos-puslapis --------------------------------------------------------- 10 0 interesų-dekraracijos --------------------------------------------------------- 14 673 kampanijos-lėšų-puslapis --------------------------------------------------------- 15 1415 kita-puslapis ---------------------------------------------------------
<databot.bot.Bot at 0x7f298a3aa9b0>
Eksportuojame, tai kas buvo išrinkta į csv
formatą, tam, kad būtų galima duomenis importuoti į Pandas įrankį.
questions.export('anketa.csv')
experience.export('patirtis.csv')
education.export('išsilavinimas.csv')
bio.export('bio.csv')
table.export('kandidatai.csv')
degree.export('mokslo-laipsnis.csv')
Importuojam visus išrinktus duomenis į Pandas.
anketa = pd.read_csv('anketa.csv').pivot(values='atsakymas', index='key', columns='klausimas')
patirtis = pd.read_csv('patirtis.csv')
išsilavinimas = pd.read_csv('išsilavinimas.csv')
biografija = pd.read_csv('bio.csv')
biografija['key'] = biografija.key.str.replace('KandidatasBiografijaHtml', 'KandidatasAnketaHtml')
biografija = biografija.set_index('key')
kandidatai = pd.read_csv('kandidatai.csv', index_col='key')
mokslolaipsnis = pd.read_csv('mokslo-laipsnis.csv', index_col='key', na_values='Nenurodė').dropna()
Panašu, kad to, kas suvesta į kandidatų anketas, niekas netikrina. Dalis duomenų surašyti laisvu tekstu, be jokios tvarkos, kaip kam patinka. Tai labai apsunkina duomenų surinkimą. Geras pavyzdys yra mokymo įstaigos pavadinimas, kur vieni pavadinimą rašo sutrumpintai, kiti pateikia pilną pavadinimą, kiti pavadinimą nurodo su gramatinėmis klaidomis, treti nurodo ne oficialų pavadinimą, o kokį nors alternatyvų, trumpesnį pavadinimą.
lietuvos = [
'lietuvos', 'vilni?ai?us', 'vilnius', 'vilniuas', 'kau[nt]o', 'klaipėdos', 'šiaulių', 'utenos',
'marijampolės', 'kelmės', 'vilkijos', 'švenčioni?ų', 'rietavo',
'joniškėlio', 'alytaus', 'smalininkų', 'švenčionėlių', 'šalčininkų', 'tauragės', 'plungės',
'vytauto', 'ri?omerio', 'stulginskio',
'žemės ūkio', 'kolegija', 'gimnazija', 'mokykla', 'valstybinė', 'technikumas',
'^teisės universitetas$', '^teisės magistras$', '^vadybos ir ekonomikos universitetas$',
'^psichologijos akademija$',
'policijos', 'medicinos', 'nenurodė', r'Elekt\.tech',
r'^.{1,3}[UAIMRĮ](\b|$)', '^.{1,5}$', '^LT ', '^kmaik$', '^važum$', '^mruni$',
]
tarptautinis_išsilavinimas = ~(
išsilavinimas['mokymo įstaiga'].str.contains(re.compile('|'.join(lietuvos), flags=re.IGNORECASE))
)
išsilavinimas[tarptautinis_išsilavinimas]['mokymo įstaiga'].value_counts().head()
/home/sirex/.venvs/databot/lib/python3.5/site-packages/ipykernel/__main__.py:13: UserWarning: This pattern has match groups. To actually get the groups, use str.extract.
Maskvos Lomonosovo universitetas 3 Balstogės universitetas 2 Maskvos M.Lomonosovo universitetas 2 Varšuvos universitetas 2 Kristiansand'o Agder universitetas (Norvegija) 1 Name: mokymo įstaiga, dtype: int64
specialybės = [
'teisė', 'viešasis administravimas', 'teisinink(as|ė)', 'politikos mokslai', 'politologija', 'vadyb(a|os)'
]
tinkamas_išsilavinimas = (
išsilavinimas.specialybė.str.contains(re.compile('|'.join(specialybės), flags=re.IGNORECASE))
)
išsilavinimas[tinkamas_išsilavinimas].specialybė.value_counts().head()
/home/sirex/.venvs/databot/lib/python3.5/site-packages/ipykernel/__main__.py:5: UserWarning: This pattern has match groups. To actually get the groups, use str.extract.
Teisė 37 Viešasis administravimas 29 Teisininkas 27 viešasis administravimas 20 Politikos mokslai 15 Name: specialybė, dtype: int64
magistras = mokslolaipsnis.value.str.contains('magistr', case=False)
daktaras = mokslolaipsnis.value.str.contains('daktar', case=False)
komunistas = ['komjaunimo', 'komunistų partijos', 'tskp narys']
komunistas = biografija.value.fillna('').str.contains(re.compile('|'.join(komunistas), flags=re.IGNORECASE))
nekomunistas = ['išaiškinant buvusių komjaunimo veikėjų', 'baigė kauno komjaunimo']
nekomunistas = biografija.value.fillna('').str.contains(re.compile('|'.join(nekomunistas), flags=re.IGNORECASE))
komunistas = komunistas & ~nekomunistas
display(biografija[komunistas].head())
biografija[komunistas].shape
value | |
---|---|
key | |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1103800&rnkId=426 | VYDAS BARAVYKAS\n\nLietuvos socialdemokratų pa... |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1104668&rnkId=426 | VINCAS BOTYRIUS\n\nAntikorupcinės N. Puteikio ... |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1102222&rnkId=426 | ALGIRDAS CEGELIS\n\nPartijos Tvarka ir teising... |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1102220&rnkId=426 | ALGIMANTAS DUMBRAVA\n\nPartijos Tvarka ir teis... |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1103926&rnkId=426 | LIUDAS JONAITIS\n\nLietuvos socialdemokratų pa... |
(25, 1)
Galiausiai išvalius visus duomenis, sudedame juos į vieną didelė lentelę, ir transformuojame duomenis į tokį pavidalį, kurį bus patogu nadoti tolesniuose skaičiavimuose.
now = datetime.datetime.now()
aukštasis = išsilavinimas.išsilavinimas == 'Aukštasis universitetinis'
kitos_kalbos = lambda v: sum(1 for x in v.split(',') if x.lower().strip() not in ('anglų', 'rusų', 'nenurodė'))
data = pd.DataFrame({
'amžius': (now - pd.to_datetime(anketa['5. Gimimo data '])).dt.days // 365,
'patirtis': patirtis[patirtis.pareigos == 'Seimo narys'].groupby('key').size(),
'anglų kalba': anketa['13. Kokias užsienio kalbas mokate '].str.contains('anglų', case=False),
'kitos kalbos': anketa['13. Kokias užsienio kalbas mokate '].apply(kitos_kalbos),
'aukštasis išsilavinimas': išsilavinimas[aukštasis].groupby('key').size() > 0,
'tarptautinis išsilavinimas': išsilavinimas[tarptautinis_išsilavinimas].groupby('key').size() > 0,
'tinkamas išsilavinimas': išsilavinimas[tinkamas_išsilavinimas].groupby('key').size() > 0,
'magistras': magistras,
'daktaras': daktaras,
'komunistas': komunistas,
})
data['patirtis'] = data['patirtis'].fillna(0).astype(int)
data['anglų kalba'] = data['anglų kalba'].fillna(False).astype(int)
data['kitos kalbos'] = data['kitos kalbos'].fillna(0).astype(int)
data['daktaras'] = data.daktaras.fillna(False).astype(int)
data['magistras'] = data.magistras.fillna(False).astype(int) | data.daktaras
data['aukštasis išsilavinimas'] = data['aukštasis išsilavinimas'].fillna(False).astype(int) | data.magistras
data['tarptautinis išsilavinimas'] = data['tarptautinis išsilavinimas'].fillna(False).astype(int)
data['tinkamas išsilavinimas'] = data['tinkamas išsilavinimas'].fillna(False).astype(int)
data['komunistas'] = data.komunistas.astype(int)
data['amžius'] = (data.amžius > 65).fillna(False).astype(int)
data.head(2).T
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1098320&rnkId=426 | http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1098342&rnkId=426 | |
---|---|---|
amžius | 0 | 1 |
anglų kalba | 1 | 0 |
aukštasis išsilavinimas | 1 | 1 |
daktaras | 0 | 1 |
kitos kalbos | 1 | 0 |
komunistas | 0 | 0 |
magistras | 0 | 1 |
patirtis | 0 | 0 |
tarptautinis išsilavinimas | 0 | 0 |
tinkamas išsilavinimas | 0 | 0 |
Žemiau panaudojus išvalytus duomenis sudedami visi balai ir gaunama viena didelė rezultatų lentelė. Balai paimti iš A. Tapino pasiūlytos formulės.
Deje, iš vrk pateiktų duomenų ne viską pavyko išgauti, todėl, ne visi kriterijai yra įvertinti.
Taip pat, tokie kriterijai, kaip išsilavinimas, nėra 100% patikimi, kadangi kai kurie kandidatai nenurodė išsilavinimo, arba išsilavinimą nurodį tik biografijoje, bet ne anketoje.
Atpažinimas ar kandidatas ėjo aukštas pareigas sovietiniame režime, taip pat nėra 100% patikimas, kadangi tokio požymio nustatymui buvo tiesiog ieškoma tam tikrų raktinių žodžių biografijoje. Jei pastebėjote, klaidų rašykite komentaruose.
def tapino_formule(res):
# - Keitęs partiją: -3 balai
#
# + Nemoka anglų kalbos: -4 balai
res['Nemoka anglų kalbos'] = (data['anglų kalba'] - 1) * 4
# + Moka daugiau kalbų (be anglų ir rusų): +2 balai už kiekvieną kalbą
res['Moka daugiau kalbų (be anglų ir rusų)'] = data['kitos kalbos'] * 2
# + Neturi aukštojo išsilavinimo: -6 balai
res['Neturi aukštojo išsilavinimo'] = (data['aukštasis išsilavinimas'] - 1) * 6
# + Turi magistro aukštąjį išsilavinimą: +2 balai
res['Turi magistro aukštąjį išsilavinimą'] = data.magistras * 2
# + Turi mokslų daktaro laipsnį: +4 balai
res['Turi mokslų daktaro laipsnį'] = data.daktaras * 4
# - Turi tik sovietinį aukštąjį išsilavinimą: -3 balai
#
# + Turi aukštąjį išsilavinimą užsienio universitete: +3 balai
res['Turi aukštąjį išsilavinimą užsienio universitete'] = data['tarptautinis išsilavinimas'] * 3
# + Išsilavinimas nesusijęs su teise, politika ar vadyba: -1 balas
res['Išsilavinimas nesusijęs su teise, politika ar vadyba'] = (data['tinkamas išsilavinimas'] - 1) * 1
# + Ėjo aukštas pareigas sovietiniame režime: -3 balai
res['Ėjo aukštas pareigas sovietiniame režime'] = data.komunistas * -3
# - Turi patirties valstybės tarnyboje ar viešajame sektoriuje užsienyje: nuo -3
# iki +3 jūsų nuožiūra (buhalterė kolūkyje šiek tiek skiriasi nuo Europos audito
# rūmų seniūno)
#
# - Visą gyvenimą užsiėmė veikla, niekuo nesusijusia nei su valstybės valdymu,
# nei su viešuoju administravimu: -4 balai
#
# - Daugiau kaip penkias kadencijas Seime: -3 balai
#
# - Daugiau kaip tris kadencijas Seime: -1 balas
#
# - Neturi patirties Seime: patys nuspręskite, kaip vertinti - pliusu ar minusu
#
# + Daugiau nei 65 metai: -2 balai (jeigu norite, kad į valdžią ateitų jaunesni,
# jeigu manote, kad valdžioje turi būti pensinio amžiaus žmonės, tada skirkite
# pliusinius balus )
res['Daugiau nei 65 metai'] = data.amžius * -2
# - Pajamų ir interesų deklaracija jums kelia įtarimų: -2 balai.
#
# Skaitykite daugiau:
# http://www.delfi.lt/news/ringas/lit/a-tapinas-lemiamas-ir-trumpas-gidas-uz-ka-balsuoti.d?id=72463294
return res
vienmadačiai = kandidatai[~kandidatai['vienmadatė apygarda.pavadinimas'].isnull()][[
'vardas',
'pavardė',
'vienmadatė apygarda.pavadinimas',
]]
vienmadačiai['kandidatas'] = vienmadačiai.vardas + ' ' + vienmadačiai.pavardė
apygardos = vienmadačiai['vienmadatė apygarda.pavadinimas'].value_counts().index
apygardos = sorted(apygardos, key=lambda x: int(x.split(None, 1)[0].rstrip('.')))
vienmadačiai['apygarda'] = pd.Categorical(vienmadačiai['vienmadatė apygarda.pavadinimas'], categories=apygardos)
vienmadačiai = vienmadačiai[['kandidatas', 'apygarda']]
res = tapino_formule(pd.DataFrame(vienmadačiai))
res = res.sort_values('apygarda').set_index(['apygarda', 'kandidatas'])
Grafikas žemiau parodo kiekvienos viemandatės kandidatų pasiskirstimą, pagal įvertinimo balą. Kaip interpretuoti šį grafiką galite sužinoti pasiskaitę Vikipedijoje.
Mėlina dėžutė rodo kandiatus nuo 25 iki 75 procentų, raudona juostelė rodo medianą, raudonas kvardatėlis rodo vidurkį, juodos juostelės iš šonų rodo ribas kur patenka mažiausią ir didžiausią balus turintys kandidatai, pluso ženklai rodo pavienius kandidatus, kurie stipriai skiriasi nuo visų kitų kandidatų.
Bendras šio grafiko vertinimas yra toks, kad visų kandidatų vidurkis yra minusinis ir tik retais atvejais kandidatai turi teigiamą įvertinimą.
columns = (res.sum(axis=1).median(axis=0, level=0)).sort_values().index.get_values()
ax = res.sum(axis=1).unstack().T[columns].plot.box(vert=False, showmeans=True, grid=True, figsize=(16, 42))
ax.set_yticklabels(['\n'.join(textwrap.wrap(x, 30)[:3]) for x in columns])
None
frame = pd.DataFrame({'balas': res.sum(axis=1)})
frame = frame.reset_index(level=1).sort_index()
for i in range(len(frame.groupby(level=0).groups)):
label = apygardos[i]
group = frame.ix[label].set_index('kandidatas').sort_values('balas')
fig = plt.figure(figsize=(16, group.shape[0] // 3))
ax = fig.add_axes([0, 0, 0.5, 1])
x = group.balas.values
y = np.arange(len(x))
categories = [
((x >= 0), 'green'),
((x < 0), 'red'),
]
for category, color in categories:
if len(category) > 0:
cx = x[category]
cy = y[category]
ax.hlines(cy, 0, cx, color=color)
ax.plot(cx, cy, 'o', color=color)
ax.plot([0, 0], [-1, len(y)], '--', color='blue')
display(HTML('<h3>%s</h3>' % label))
ax.set_yticks(y)
ax.set_yticklabels(['%30s' % group.index[0]] + list(group.index)[1:], family='Ubuntu Mono')
ax.set_xlabel('Balas')
ax.set_ylabel('Kandidatas')
plt.xlim(-20, 15)
plt.ylim(-1, len(y))
plt.grid()
plt.show()
daugiamandačiai = kandidatai[~kandidatai['sąrašas.pavadinimas'].isnull()][[
'vardas',
'pavardė',
'sąrašas.pavadinimas',
'numeris sąraše',
]].rename(columns={'sąrašas.pavadinimas': 'sąrašas'})
daugiamandačiai['kandidatas'] = daugiamandačiai.vardas + ' ' + daugiamandačiai.pavardė
daugiamandačiai['numeris sąraše'] = daugiamandačiai['numeris sąraše'].str.strip().astype(int)
sąrašas = daugiamandačiai.sąrašas.value_counts().index
sąrašas = sorted(sąrašas, key=lambda x: int(x.split(None, 1)[0].rstrip('.')))
daugiamandačiai['sąrašas'] = pd.Categorical(daugiamandačiai.sąrašas, categories=sąrašas)
daugiamandačiai = daugiamandačiai[['kandidatas', 'sąrašas', 'numeris sąraše']]
daugiamandačiai.head(3)
kandidatas | sąrašas | numeris sąraše | |
---|---|---|---|
key | |||
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1103268&rnkId=426 | Regina ABLOM | 11. Lietuvos lenkų rinkimų akcija-Krikščionišk... | 43 |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1103624&rnkId=426 | Inga ABRUTYTĖ | 7. Lietuvos Respublikos liberalų sąjūdis | 115 |
http://vrk.lt/pub/webcontent/kandidatai/lrsKandidatasAnketaHtml?rkndId=1104220&rnkId=426 | Kęstutis AČAS | 2. Tėvynės sąjunga - Lietuvos krikščionys demo... | 69 |
res = tapino_formule(pd.DataFrame(daugiamandačiai))
res = res.sort_values(['sąrašas', 'numeris sąraše']).set_index(['sąrašas', 'kandidatas'])
del res['numeris sąraše']
res.head(5).T
sąrašas | 1. Lietuvos socialdemokratų partija | ||||
---|---|---|---|---|---|
kandidatas | Algirdas BUTKEVIČIUS | Algirdas SYSAS | Rasa BUDBERGYTĖ | Juozas OLEKAS | Raminta POPOVIENĖ |
Nemoka anglų kalbos | -4 | 0 | 0 | 0 | -4 |
Moka daugiau kalbų (be anglų ir rusų) | 0 | 2 | 2 | 0 | 2 |
Neturi aukštojo išsilavinimo | -6 | 0 | -6 | 0 | 0 |
Turi magistro aukštąjį išsilavinimą | 0 | 0 | 0 | 2 | 0 |
Turi mokslų daktaro laipsnį | 0 | 0 | 0 | 4 | 0 |
Turi aukštąjį išsilavinimą užsienio universitete | 0 | 0 | 0 | 0 | 0 |
Išsilavinimas nesusijęs su teise, politika ar vadyba | -1 | -1 | -1 | -1 | -1 |
Ėjo aukštas pareigas sovietiniame režime | 0 | 0 | 0 | 0 | 0 |
Daugiau nei 65 metai | 0 | 0 | 0 | 0 | 0 |
columns = res.sum(axis=1).median(axis=0, level=0).sort_values().index.get_values()
ax = res.sum(axis=1).unstack().T[columns].plot.box(vert=False, showmeans=True, grid=True, figsize=(16, 16))
ax.set_yticklabels(['\n'.join(textwrap.wrap(x, 30)[:3]) for x in columns])
None
nres = res[daugiamandačiai.set_index(['sąrašas', 'kandidatas']).sort_index()['numeris sąraše'] <= 20]
columns = nres.sum(axis=1).median(axis=0, level=0).sort_values().index.get_values()
ax = nres.sum(axis=1).unstack().T[columns].plot.box(vert=False, showmeans=True, grid=True, figsize=(16, 16))
ax.set_yticklabels(['\n'.join(textwrap.wrap(x, 30)[:3]) for x in columns])
None
/home/sirex/.venvs/databot/lib/python3.5/site-packages/ipykernel/__main__.py:1: UserWarning: Boolean Series key will be reindexed to match DataFrame index. if __name__ == '__main__':
frame = pd.DataFrame({
'balas': res.sum(axis=1),
'numeris sąraše': daugiamandačiai.set_index(['sąrašas', 'kandidatas'])['numeris sąraše'],
})
frame = frame.reset_index(level=1).sort_index()
for i in range(len(frame.groupby(level=0).groups)):
label = sąrašas[i]
group = frame.ix[label].set_index('kandidatas').sort_values('balas')
x = group.balas.values
y = np.arange(len(x))
display(HTML('<h3>%s</h3>' % label))
# Scatter plot
display(HTML('<p>Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:</p>'))
ax = None
categories = [
((group.balas >= 0), 'green'),
((group.balas < 0), 'red'),
]
for category, color in categories:
if category.sum() > 0:
ax = group[category].plot.scatter(x='numeris sąraše', y='balas', color=color,
grid=True, figsize=(16, 3), ax=ax)
xlim = [0, len(x)]
ax.plot(xlim, [0, 0], '--', color='blue')
plt.xlim(*xlim)
plt.ylim(-20, 20)
plt.show()
# Stem plot
limit = 20
display(HTML('<p>Top %d kandidatų iš partijos, pagal balą:</p>' % limit))
fig = plt.figure(figsize=(16, limit // 3))
ax = fig.add_axes([0, 0, 0.5, 1])
x = x[-limit:]
y = np.arange(len(x))
format_yticklabel = lambda x: '%s (%s)' % (x.kandidatas, x['numeris sąraše'])
yticklabels = group.reset_index()[-limit:].apply(format_yticklabel, axis=1).values
categories = [
((x >= 0), 'green'),
((x < 0), 'red'),
]
for category, color in categories:
if len(category) > 0:
cx = x[category]
cy = y[category]
ax.hlines(cy, 0, cx, color=color)
ax.plot(cx, cy, 'o', color=color)
ax.plot([0, 0], [-1, len(y)], '--', color='blue')
ax.set_yticks(y)
ax.set_yticklabels(['%30s' % yticklabels[0]] + list(yticklabels)[1:], family='Ubuntu Mono')
ax.set_xlabel('Balas')
ax.set_ylabel('Kandidatas (numeris sąraše)')
plt.xlim(-20, 20)
plt.ylim(-1, len(y))
plt.grid()
plt.show()
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą:
Visi partijos kandidatai surūšiuoti pagal sąrašo eilės numerį:
Top 20 kandidatų iš partijos, pagal balą: