Jak jsem bojovala se scénářem GoT
Když jsem se v lednu rozhodovala, o čem budu psát svůj závěrečný projekt digitální akademie Czechitas, analýza textu scénáře seriálu Game of Thrones pro mě byla jasnou volbou. No, nevím, jak vy, které jste si DA prošly, ale já jsem postupně své téma asi 5x změnila, vždy ve víře, že na to, co jsem si vymyslela, seženu data. Jenže ono to tak vůbec nebylo — když už byly nějaká data k dispozici, postrádaly některé údaje, které jsem sháněla, nebo naopak firmy nebyly vůbec ochotné data poskytnout. Když selhalo i téma od mentora a do odevzdání projektu zbývalo 16 dní, začala úroveň mého stresu šplhat až do nebeských výšin.
Spojila jsem se tedy s Michalem Šimonem, který naštěstí souhlasil, že mi s projektem do začátku pomůže. Společně jsme se pustili do psaní kódu v Pythonu (za což jsem byla opravdu ráda, protože mě Python na hodinách hodně bavil). Nejklasičtější klávesovou zkratkou Ctrl+C a Ctrl+V jsem si do textového souboru zkopírovala text první epizody a začali jsme se společně dívat na to, jak text rozdělit.
Tím, že byly jména postav v kapitálkách a text byl oddělen dvojtečkou, poradil mi Michal, abych pro oddělení postavy a textu použila regulárních výrazů (regular expressions). Společně jsme si pak otevřeli Online regex tester a debugger, abych si vyzkoušela, jak tato metoda funguje a rovnou viděla, které části textu budou vybírány.
Nakonec jsme došli k tomuto kódu, který nám pomohl oddělit text od postavy, níže je vidět, které části jsou obsaženy v jednotlivých částech regulárního výrazu.:
(?P<name>[A-Z0–9 ]+)(?P<comment> \(.*\))*: (?P<speech>.*)
Tento kód měl před dvojtečkou brát vše jako jméno s tím, že jméno může obsahovat velká písmena, mezery a číslice (protože se nám tam objevily i případy „MAN 1“, „NIGHTS WATCH BROTTHER 2“ a další.
2 příklad řešení z Online regex tester and debugger — použití na první epizodě
Hned u druhé epizody jsme ale narazili na problém — postavy nebyly napsány v kapitálkách. Proto jsme výraz upravili tak, aby bral v úvahu i malá písmena.
(?P<name>[a-zA-Z0–9 ]+)(?P<comment> \(.*\))*: (?P<speech>.*)
Když jsme si už zjistili, co vlastně budeme z textu vybírat, mohli jsme se pustit do psaní samostatného skriptu. Nejdřív jsme si samozřejmě museli nadefinovat funkce pro získání souborů epizod a jejich přečtení. Tyto funkce jsme nadefinovali v samostatném skriptu s tím, že jsme je pak jednotlivě importovali.
3 Skript v Pythonu — získávání a čtení souborů
Procházka sedmi pekly— příprava a čištění dat
Už když jsme začínali se psaním skriptu, upozornil mě Michal na to, že analýza jako taková bude relativně jednoduchá, ale že se mám připravit na to, že strávím spoustu času s editací textu. No a asi Vás nepřekvapí, že měl naprostou pravdu. V GoT mají 7 bohů a 7 pekel, a já jsem si několika z nich při získávání a čištění dat prošla. Každá epizoda byla napsána trošku jinak — ať už šlo o upper nebo lower case, popisky scén, které jsme chtěli přeskočit nebo o to, že postavy byly často nazývány různými jmény.
Perfektním příkladem byla Daenerys Targaryen — postava, která používá v celé sáze nejvíce titulů vůbec, měla asi 5 nejčastějších aliasů — Daenerys, Daenerys Targaryen, Daenerys Stormborn, Dany, Khaleesi. No a pak tady taky byly překlepy (taky si mohl G. R. R. Martin vymyslet trošku snazší jména, že ano?) — a tak jsem se setkala s Danerys, Daerenys a jinými.
4 “Daenerys of the House Targaryen, the First of Her Name, The Unburnt, Queen of the Andals, the Rhoynar and the First Men, Queen of Meereen, Khaleesi of the Great Grass Sea, Protector of the Realm, Lady Regnant of the Seven Kingdoms, Breaker of Chains and Mother of Dragons”.
Ale ani to všechno nebylo nic proti tomu, co mě čekalo až v tom pomyslném sedmém pekle. Tím myslím zjištění, že asi k 27 epizodám chybí scénáře — respektive byly k dispozici titulky, kde ale nebylo uvedeno, která osoba mluví. Ať jsem hledala, jak jsem jen mohla, nejlepší varianta, kterou jsem objevila, vypadala takto:
5 Vzor přepsaných titulků u epizod, ke kterým chyběl scénář
Samozřejmě, že jsem si řekla, že se s tímto textem nespokojím, a tak začal můj sledovací maraton hry o trůny, kdy jsem texty v podobě výše upravovala do podoby, kterou jsem chtěla. To znamená, že jsem si všech 27 epizod musela přehrát a ke každému řádku doplnit jméno, případně věty pospojovat mezerou a ne novým řádkem, pokud šlo o souvislý text (jeden výstup v rámci dialogu), nebo dokonce řádky rozdělovat, protože se někdy stalo, že na jednom řádku byly texty více postav. Tato část mi zabrala asi 45 hodin čistého času — naštěstí mi to ale velmi usnadnilo plánování volného času (protože jsem prakticky žádný neměla).
6 Upravený text do žádoucího formátu
Kromě mých “základních” dat jsem se rozhodla, že si přidám ještě trošku jiná data, a tak jsem si vytvořila tabulku, kde jsem měla uvedené označení epizody a informace, kdo ji režíroval / napsal a jaké je jeho/její pohlaví (říkala jsem si, že zkusím vyvrátit stereotyp, že jsou ženy nejukecanější — k tomu se ale dostaneme až později).
Začínáme psát skript
Jedno se rozhodně nedá Michalovi upřít — a tím je to, že má opravdový zájem o to, aby holky zvládaly (nebo se o aspoň pokoušely) psát práci samy. Společně jsme ze startu strávili cca 6 hodin na tom, abychom nadefinovali v pythonu načtení a přečtení souboru, nastavit rozdělení textu na slovník, kde klíčem byla postava (name/character) a hodnotou byl text, který říka (speech). Musím říct, že jestli jsem si na tomhle projektu něco procvičila, tak to byla práce se seznamy, slovníky a cykly.
Výsledkem bylo .csv, ve kterém bylo uvedeno jméno postavy, text, který říká a informace o tom, kolik výstupů v dané epizodě daná postava měla.
Pak jsem si říkala, že by kromě počtu výstupů nebyla špatná informace, kolik slov daná postava říká (jestli se může např. někdy stát, že má jedna postava 3 výstupy, ale řekne během nich to, co jiná za 10). Postupně jsem tedy očistila text a rozdělila pomocí splitu jednotlivá slova.
Při přípravě tohoto kódu jsem se musela zamyslet nad tím, jak budu řešit klasická anglická spojení typu “don’t”, “won’t”, “he’s” a jiné. Bude se to počítat jako jedno nebo dvě slova? Vzhledem k tomu, že v tomto případě jde o sdružení dvou slov “do not”, “willl not” nebo “is not”, rozhodla jsem se, že to budu počítat jako dvě samostatná slova. Byla zde sice i možnost přivlastňovacího “ ‘s ”, ale tyto případy byly spíše ojedinělé v porovnání s předchozím.
7 Skript v Pythonu na vyfiltrování prázdných a popisných řádků a vytvoření skupin name a speech
8 Skript v Pythonu na rozdělení textu na slova a jejich následné počítání
9 nastavení exportu základní části do csv
Níže je vidět výstup z csv (otevřeno v excelu), kde ve sloupci 1 je název postavy, ve sloupci 2 je počet výstupů, ve sloupci 3 je počet slov a ve sloupci 4 je pak samotný text. Pro každý textový soubor se scénářem epizody vznikl samostatný soubor se základními informacemi o postavách, které v daném díle vystupovaly a alespoň jednou promluvily.
10 výstup první části skriptu v csv
Jaká je v GoT nálada?
Pak jsme se mohli podívat na další část projektu, a to počítání sentimentu. Nejdříve jsem vytvořila slovník AFINN111 , ze zdroje, který je veřejně dostupný a obsahuje cca 2500 nejběžnějších anglických slov a spojení, které mají citové zabarvení.
11 vytvoření slovníku sentimentu
Slova jsou hodnocena na škále <-5,+5>, podle toho, jak jsou pozitivní či negativní, a v souboru jsou od hodnot odděleny tabulátorem, proto je zvolen .split(‘\t’).
Do analýzy sentimentu jsem se pustila s tím, že jsem doufala, že naprostá většina negativních postav bude mít navzdory svým činům pozitivní slovník, protože jde přece jen o seriál plný intrik, pastí, podrazů a vrážení kudel do zad.
Opět jsem hodně pracovala s cykly. Nejdřív jsme pro každé slovo, které bylo ve slovníku sentimentu, hledali, jestli je použito v textu postavy. Pokud bylo, zvýšilo (případně snížilo) se skóre sentimentu dané postavy a zároveň se přičetla 1 k celkovému počtu citově zabarvených slov. Na konci cyklu se pro postavu spočítala průměrná hodnota sentimentu, a to klasickým průměrovým vzorcem = celkové skóre sentimentu děleno počtem citově zabarvených slov na postavu. Tento cyklus samozřejmě nebyl úsporný v tom, že pro každé slovo se nejdříve musel projet celý slovník. Ale nebojte, to jsem později napravila.
12 Skript pro počítání sentimentu
13 Output v příkazovém řádku při počítání sentimentu
14 Export csv s hodnotami sentimentu
15 csv výstup ze skriptu počítajícího sentiment
Jde to dělat i čistěji a úsporněji
Jestli vám teď připadá kód nepřehledný a zbytečně dlouhý, máte asi pravdu. Tento kód byl ideální na to, abych si dokázala vyrobit výstup s co nejpodrobnějším psaním kódu po jednotlivých mikrokrůčcích. Sice jsem se v něm zvládala orientovat a chápala jsem, co který řádek dělá, ale když jsem chtěla přidat funkci, skákala jsem z jednoho souboru do druhého, protože se mezi nimi často funkce importovaly.
Poprosila jsem tedy o pomoc Lumíra (kterého považuji jednak za skvělého lektora a taky za takového python guru 🙂 ), jestli by se se mnou na ten kód a projekt nepodíval a jestli nebude mít návrh na úspornější řešení. Když jsem mu říkala, že ještě musím dokoukat posledních 12 epizod, abych měla kompletní data, tak mi řekl, že bych pak určitě měla svá data na původní stránce se skripty nasdílet, abych se o tu práci podělila (což samozřejmě udělám, přece si to nenechám pro sebe, že jo).
Lumír mi ukázal, jak napsat kód tak, aby nezabral tolik místa a byl celkově čitelnější a dalo se v něm lépe orientovat. Naučila jsem se zase pár nových funkcí a taky třeba metodu dictionary comprehension, kdy se vytvoření slovníku dá napsat na jediný řádek (a tomu opravdu říkám úspora).
Navíc jsme tentokrát nemíchali české a anglické názvy proměnných a celý kód udržovali v angličtině.
16 extrakce slovníku character/actor — speech
17 vytvoření slovníku sentimentu v novém řešení
18 vytvoření funkce pro počítání statistik v novém řešení
19 Spuštění nadefinované funkce pro výpočet statistik a uložení do samostatného csv
20 vytvoření kompletního csv se všemi informacemi
Výsledné csv po otevření v excelu vypadalo přibližně takto:
21 Vysvětlení jednotlivých sloupců k exportovanému csv
22 Výsledné csv s daty
No a jak vidíte, musela jsem Vám nahoru hodit legendu, protože mi samozřejmě nevyjížděly názvy sloupců. Pro jejich vytvoření jsem sáhla po jupyter notebooku, kde jsem si mohla hned otestovat, jestli mi “headers” naskočí. Samozřejmě jsem později zjistila, že jde záhlaví napsat i mnohem jednodušeji, ale tohle bylo řešení, na které jsem společně s googlem přišla sama a měla jsem z něj velkou radost. Výsledkem mi bylo nové “complete_headers.csv”.
23 Vytvoření záhlaví v csv
Když jsem si pak ale kontrolovala průměrné hodnoty sentimentu, zjistila jsem, že mi nevychází stejné hodnoty, jako dříve. Tak jsem se na to podívala podrobněji. Ve skriptu, který jsem napsala s Michalem, jsem si “vyprintla” jednotlivá slova, která rozpoznal python jako citově zabarvená, a díky tomu jsem mnohem rychleji našla tu chybu. Zatímco mi můj nový skript řekl, že Royce v první epizodě použil 7 citově zabarvených slov ze slovníku, tady jich bylo 14. Bral totiž v úvahu i části slov. Například v jeho scénáři nebylo slovo “gain”, “ha” nebo “ill”, ale zato tam bylo “again”, “what” a “will”. Takže se mi aspoň potvrdilo, že nové výpočty budou pravděpodobně ty správné.
24 hledání chyby v počítání sentimentu
Osmé peklo existuje — dočišťování dat
Když jsem měla v csv všechna jména, daly se teprve pořádně a přehledně vyčistit. Když jsem si otevřela csv s kódováním UTF-8 v excelu, mohla jsem si seřadit jednotlivé řádky podle jmen postav a začala jsem si kontrolovat, jestli se mi všechny postavy jmenují stejně. Zjistila jsem, že se mi ještě stále objevují určité inkonzistence, co se jmen postav týče. Např. “ALLISER” — “ALISSER”, “RAMSAY” — “RAMSEY” nebo “JAQUEN” a “JAQEN”. Vše jsem si opravila (když jsem to projížděla potřetí, vypadalo to, že už to mám jakž takž zkontrolované a že už by tam nemělo být nic, co by vadilo).
Když jsem si pak ale uploadovala zdroj do Power BI, zjistila jsem, že mi vizualizace u některých postav, i když mají stejný název, vytváří dvě série. Např. u epizody S01E02 to vypadalo, že pro postavu “JORAH” to vytváří 2 odlišné řady. Zkusila jsem si teda csv natáhnout znovu, tentokrát s kódováním pro Evropu, a zjistila jsem, že se mi u postav, které jsou na prvním řádku souboru, objevují „neviditelné“ znaky. Nejdřív jsem se zkusila tomu vyhnout tak, že jsem posunula celý text o jeden řádek níže, čímž mi vznikly položky s null hodnotami, zároveň mi ale všechny postavy zůstaly správně označené.
I tak se mi ale nezdálo, že jde o správné řešení, takže jsem to ještě v pátek před odevzdáním řešila s Pavlem. Ten mi poradil, ať si všechny soubory se scénáři epizod otevřu a přeuložím je tak, aby byly uloženy s kódováním UTF-8, nikoliv UTF-8 with BOM. To naštěstí pomohlo a tímto považuji čištění dat za ukončené.
25 Ukldání textu se správným kódováním v Sublime Textu
Už jsem se jen mohla těšit na vizualizaci dat.
Třešnička na dortu — vizualizace
Když jsem se rozhodovala, v čem budu chtít data vizualizovat, bylo mi jasné, že primárně to bude Power BI, protože mě práce s tímto nástrojem s Adélkou hodně bavila.
Rozhodla jsem se ale, že si zkusím udělat nějakou základní analýzu a vizualizaci v Jupyter Notebooku, který nám Lumír ukazoval. Pro práci s analýzou v Jupyter Notebooku jsem si ještě potřebovala doinstalovat některé knihovny, ale protože jsem s instalací samostatných knihoven měla problém, pomohl mi Pavel s instalací Anacondy, která už potřebné knihovny obsahuje.
Zkontrolovala jsem si, jestli nemám náhodou nějaké null hodnoty a zkusila jsem si provést pár jednoduchých analýz — vybrat si postavy, které mají za epizodu největší počet výstupů / slov, to samé pro souhrny za epizodu / sérii.
26 Jupyter notebook — nejupovídanější epizody
26 Jupyter notebook — nejupovídanější epizody
28 Jupyter notebook — nejupovídanější postavy podle počtu výstupů
29 Power BI — poměr počtu slov na výstup u Neda Starka
30 Power BI — vytvoření nového sloupce SE— nadefinování v DAXu
31 Nastavení propojení obou zdrojových tabulek v Power BI
Srovnání upovídanosti epizod a sérií
Na začátek jsem se v Power BI podívala na porovnání počtů slov a dialogů v epizodách (vždy např. první epizoda pro všechny série). Jak můžeme vidět, nejméně se toho obecně namluví v devátých epizodách všech sérií. Kdybych seriál neznala, tak řeknu, že vysvětlení může být to, že v 7. sérii bylo pouze 7 epizod, což vystavilo deváté epizody do značné nevýhody. Pravdou ale je také to, že ve 2., 4., 5. a 6. sérii byly v devátých epizodách bitvy. A co si budeme povídat, když se bojuje, není čas se vykecávat. ?
32 Power BI — Porovnání počtů slov a dialogů podle epizod
33 Porovnání počtů slov a dialogů podle sérií
34 Power BI — “heat” tabulky podle počtu dialogů (vrchní tabulka) a počtu slov (spodní tabulka)
35 Power BI — porovnání počtů slov a dialogů chronologicky po jednotlivých epizodách
36 Power BI Clusterový graf — porovnání pohlaví scénáristy a upovídanosti epizod
A jak jsou ukecané jednotlivé postavy?
Pak jsem se samozřejmě chtěla podívat na upovídanost jednotlivých postav. Konec konců, právě proto jsem si dala tolik práce s přepisováním scénářů. Asi nikoho nepřekvapí, že toho nejvíc namluví Tyrion, ale přijde mi zajímavé, že ne vždy souhlasí pořadí u počtů slov a počtů výstupů. Znamená to tedy, že některé postavy, když dostanou příležitost mluvit, toho řeknou v jednom výstupu více než ty, které se v dialozích objevují častěji. Např. taková Cersei má pouze o 22 výstupů méně než Jon Snow, ale zato během nich stihne říct o téměř 4 000 slov více.
37 Power BI — sloupcový graf — nejupovídanější postavy napříč celým seriálem
38 Power BI — tabulkové přehledy nejupovídanějších postav podle počtu výstupů, počtu slov a poměru počtu slov na jeden výstup
39 — Power BI — počet “unikátních” postav v jednotlivých epizodách / sériích
“I told you not to trust me.”
To je jedna z nejznámějších hlášek celého seriálu, která podle mě hodně vystihuje intrikářství celé ságy a potvrzuje i výsledek, který jsem na začátku očekávala. Postavy, které kolikrát používají pozitivní slova, nevyjadřují se vulgárně, jsou většinou jedny z těch nejzákeřnějších. Perfektními případy jsou například Euron, Baelish, Cersei nebo Ramsay. Naopak postavy, které jsou vesměs kladné, se mohou pohybovat v záporných hodnotách (např. Arya, Jon Snow), protože jsou prostě pesimistické a volí podle toho i svá slova. Postava Tyriona je opět speciální — průměrná hodnota jeho sentimentu je přesně na hodnotě 0,00 — považuji ho za kladnou postavu, která si ale nebere servítky a vždy na plnou pusu řekne, co si myslí — a pro sprosté slovo nejde daleko.
40 Power BI — sentiment jednotlivých postav podle hodnot průměrného sentimentu citově zabarvených slov
41 Power BI — sentiment jednotlivých sérií podle hodnot průměrného sentimentu citově zabarvených slov
Závěr
A co bych chtěla s tímto projektem dělat dále? Určitě bych se chtěla podívat na to, jestli to jde napsat jednodušeji / efektivněji, protože Lumír mi tvrdí, že to jde 🙂 Díky této analýze jsem taky zjistila, že znalost tématu může opravdu hodně pomoci s objasněním výkyvů a trendů a oživit interpretaci výsledků.
Zároveň bych se chtěla podívat na to, jestli jde sestavit slovníček nejčastějších slov pro jednotlivé epizody nebo série, aby se dal udělat takový materiál typu „Chcete se dívat na GoT v originále? Tak to byste se měli naučit tahle slovíčka.“ Pokud se učíte cizí jazyky, určitě sami nejlépe víte, že se skvěle učí u filmů / knížek / písniček. Tak proč si tento způsob učení trošku nevylepšit?
Doufám, že dalším krokem by pak mohlo být přizpůsobení této metody i na jiné cizojazyčné filmy nebo texty k písničkám. Myslím si, že pro takovou španělštinu by to mohla být trošku větší výzva, protože na rozdíl od angličtiny mají časování, při kterém se mohou měnit i kořeny slov. Takže si myslím, že taková písnička “Despacito”, jejíž slova skoro nikdo neumí a ani neví, o co v té písničce jde, by mohla být pěkný pokusný králík.
Na závěr bych chtěla poděkovat nejen starým i novým bohům Západozemí, že jsem psaní projektu ve zdraví zvládla, ale zejména i několika dalším lidem. Rodině, kamarádům a Vaškovi, že to se mnou vydrželi, protože ke konci jsem prakticky fungovala jenom s počítačem, nikam jsem nechodila a o ničem jiném než o projektu se nebavila. No a nejvíc ze všeho bych chtěla poděkovat třem skvělým osobám, které mi pomáhali s projektem nejvíce. Lumírovi, Pavlovi a Šimonovi, kteří mě v tom nenechali vykoupat a pomohli mi, jak to jen bylo možné, a Adéle, která mi dala spoustu rad ohledně Power BI. Díky moc.
Nejzajímavější výsledky jsme vizualizovali do infografiky
No a v tu chvíli jsem se zamyslela, k čemu bych mohla volně dostupná data sehnat. Přemýšlela jsem o věcech, které mě baví a ke kterým mám blízko, a napadlo mě, že bych mohla psát o Hře o trůny, se kterou jsem v závěru roku 2017 v nemocnici strávila spoustu času. Vzpomněla jsem si na první hodinu úvodu do datové analýzy, na které nám Michal Šimon říkal o možnosti analýzy textu a sentimentu.
Kdybych chtěla dělat pouze analýzu textu, asi by to bylo jednodušší, ale já jsem si samozřejmě na sebe musela „ušít bič“ a chtěla jsem dělat analýzu scénářů, ve kterých budou přímo uvedeny názvy / jména postav, které mluví. Tak se mi otvírala možnost porovnávat to, jaký prostor dostává která postava v jednotlivých epizodách / sériích a porovnávat jejich sentiment.
Vzhůru do boje
Samozřejmě jsem hledala scénář v angličtině, aby odpadala starost se skloňováním a časováním. Po dlouhém hledání jsem na stránkách https://genius.com opravdu našla formát, který se zdál, že by mohl vyhovovat. Postava byla vždy v kapitálkách a oddělená dvojtečkou.