gulární výrazy, práce s textem a daty IBlil Úvod do programování skrze Python 2013 Práce s textem Příklady: • statistiky o studentech • frekvenční analýza textu • zpracování dotazníku, an Čeština • v tomto kurzu pro zjednodušení pracujeme jen s anglickou abecedou • resp. s texty bez hacku a carek • pro zájemce viz např. http://www.py.cz/PythonUnicodeCestina • základ: specifikovat kódování na začátku souboru # -*- coding: utf-8 -*- ulární výrazy: motivace • vyhledání e-mailových adres v textu • vyhledání odkazů v HTML dokumentu • náhrada „jméno příjmení" za „příjmení jméno" • změna formátu datumů • odstranění bílých znaků Regulární výrazy: použití • programování • textové editory • příkazová řádka: např. grep • teorie: formální jazyky, konečné automaty Regulární výrazy • obecně používaný nástroj • základní syntax stejná ve většině jazyků, prostředí • následuje: • základní syntax regulárních výrazů • použití v Pythonu • nerozebíráme všechny technické detaily (podrobněji viz dokumentace) import re f = openCtestovaci-soubor.txt") for radek in f .readlinesO : if re. search(r' [a-z]+@ [a-z]+\. cz', radek): print radek f closeO Znaky a speciální znaky • základní znak „vyhoví" právě sám sobě • např. „cz" v předchozím příkladě • speciální znaky: .~$* + ?{}[]\l() • umožňují konstrukci složitějších výrazů • chceme, aby odpovídaly příslušnému symbolu =4> prefix \ Výběr ze skupiny znaků [] • [abc] - jeden ze znaků a, b, c • [a-z] - výběr z intervalu (malé písmeno anglické abecedy) • ~ na začátku výběru = negace: • [~abc] cokoliv jiného než a, b, c Často používané skupiny znaků \d Čísla: [0-9] \D Cokoliv kromě čísel: [~0-9] \s Bílé znaky: [ \t\n\r\f \v] \S Cokoliv kromě bílých znaků: [~ \t\n\r\f\v] \w Alfanumerické znaky: [a-zA-Z0-9_] \W Nealfanumerické znaky: [~a-zA-Z0-9_] Speciální symboly libovolný znak začátek řetězce konec řetězce alternativa - výběr jedné ze dvou možností 11/54 Příklady Jaký je význam následujících výrazů? • kocka|pes • ~a.*a$ • \d[A-Z]\d \d\d\d\d 12/54 Opakování * nula a více opakování + jedno a více opakování ? nula nebo jeden výskyt {m,n} m až n opakování 13/54 Příklady Která z následujících slov vyhoví jednotlivým výrazům? p[ars]e p[ars]*e p[~ars]e ps pes pse poe prase poklice 14/54 Příklady Která z následujících slov vyhoví jednotlivým výrazům? p[ars]e p[ars]*e p[~ars]e ps X X X pes X / X pse / / X poe X X / prase X / X poklice X X X 15/54 Kontrola tabulky v Pythonu texty = ["ps","pes","pse","poe","prase","poklice"] výrazy = [ r'p[ars]e', r'p[ars]*e', r'p[~ars]e' ] for text in texty: print text, for vyraz in výrazy: if re.search(vyraz, text): print 1, else: print 0, print 16/54 Příklady Jaký je význam následujících výrazů? • \d{3}\s?\d{3}\s?\d{3} • [a-z]+@[a-z]+\.cz • ~To:\s*(fi Ikit)(-int)?@fi.muni.cz 17/54 Regulární výrazy v Pythonu • knihovna re (import re) • re.match - hledá shodu na začátku řetězce • re. search - hledá shodu kdekoliv v řetězci • (re. compile - pro větší efektivitu) • „raw string" - r'vyraz' - nedochází k interpretaci speciálních znaků jako u běžných řetězců v Pythonu 18/54 ulární výrazy v Pythonu: práce s výsledkem • match/search vrací „MatchObject" pomocí kterého můžeme s výsledkem pracovat • pomocí kulatých závorek () označíme, co nás zajímá • Alice\s+(\w+) Regulární výrazy v Pythonu: práce s výsledkem »> m = re.match(r"(\w+) (\w+)", \ "Isaac Newton, fyzik") »> m.group(0) 'Isaac Newton' »> m.group(1) 'Isaac' »> m.group(2) 'Newton' • nahrazení řetězce jiným výrazem • nejen statické řetězce, ale i regulární výrazy • re.sub 21/54 Rozdělení řetězce • split - rozdělí řetězec podle zadaného podřetězce, vrací seznam částí • join - spojení seznamu řetězců do jednoho »> řetězec = "Holka modrooká nesedavej u potoka" »> řetězec. split () ['Holka', 'modrooká', 'nesedavej', 'u', 'potoka'] »> řetězec. split ('o') ['H', 'lkam', 'dr', ", 'ka nesedavej up', 'ť, 'k >» řetězec. split ('ka') ['Hol', ' modroo', ' nesedavej u poto', ''] 22/54 Řetězce: další funkce • find, count - vyhledávání a počítání podřetězců • lower, upper - převod na malá/velká písmena a ljust, rjust, center - zarovnání textu • lstrip, rstrip - ořezání bílých znaků na začátku/konci 23/54 Práce se soubory - připomenutí Otevírání a zavírání: • f = open("mujsoubor.txt") - otevření pro čtení • f = open("muj soubor .txt", "w") - otevření pro zápis • f.closeO - uzavření souboru • zápis pomocí with - lepší praxe (ale pokročilejší, souvisí s výjimkami) Čtení a zápis: • f .readlineO - vrátí další řádek ze souboru • f . readlines () - vrátí seznam všech zbývajících řádků • f .write (řetězec) - zapíše do souboru 24/54 Příklad: Zpracování HTML • vstup: HTML soubor • cíl: vybrat odkazy a nadpisy • ukážeme naivní řešení se soubory, reg. výrazy • systémovější řešení: využití knihoven pro práci s URL zdroji, parsování HTML 25/54 Zpracování HTML Faculty ol Informatics Masaryk University
Australie< / td> | dolflE< / tdxtd align=" right" >l | AUD20 , A5A aligns right w>lBRl9, 706Eulharsk.olev | horuna=:ytdxtd align="right">lAust)
• rozdělit na řádky tabulky (podle | |
Aust',radek): for radek_tab in radek.split(' | ||||
( [A-Z]{3}).*right">([\d,]+) | radek_tab) kurzy[m.group(l)] = float(re.sub(',m.group(2))) soubor.close() return kurzy 4 S ► < -š ► * = * 33/54 Příklad: informace o studentech Export informací z ISu (CSV soubor): 1. ;50668;"Sukany, Martin";zk;"FI B-AP BcAP [sem 1, roc 2. ;421714;"Veznik, Ondrej";zk;"FI B-AP SOCI [sem 2, ro< 3. ;564138;"Machala, David";zk;"FI B-AP BcAP [sem 1, ro< 4. ;43583;"Mikes, Martina";zk;"FF B-FI PLIN [sem 5, cyk 5. ;81908;"Sulc, Tomas";zk;"FF B-FI PLIN [sem 5, cyk 1]' 6. ;844632;"Novák, Karel";zk;"FI B-IN PSK [sem 1, roc 1! 7. ;798639;"Dunickova, Dagmar";zk;"FI B-AP SOCI [sem 1, 8. ;195660;"Stipsky, Tomas";zk;"FI B-AP BcAP [sem 1, ro< 9. ;278740; "Fojt, Roman" ;zk; "FI B-AP INVS [sem 3, roc 2~_ 10. ;236293;"Zachar, Samuel";zk;"FI B-IN UMI [sem 1, ro< Pozn. Příklad je „mutovaný" z důvodu ochrany osobních údajů. 34/54 Statistiky o studentech • výpis křestních jmen (abecedně seřazený) • statistika studovaných oborů 35/54 Výpis křestních jmen def krestni_jmena(jmeno_souboru): f = open(jmeno_souboru) jména = [] for radek in f .readlinesO : m = re.match(r'\d+\.;\d+;"\w+, (\w+)', radek) if m: jména append(m.group(1)) jména.sort() print " ".join(jména) f.close() Jiné řešení: použití split 36/54 Statistiky oborů def obory(jmeno_souboru): f = open(jmeno_souboru) vyskyty_oboru = {} for radek in f .readlinesO : m = re.search(r'\s(\w+) \[sem', radek) if m: obor = m.group(l) vyskyty_oboru[obor] = \ vyskyty_oboru.get(obor, 0) + 1 f.close() for obor in vyskyty_oboru.keys(): print obor, vyskyty_oboru[obor] Nedostatky: např. studenti studující více oborů. 37/54 rocvičení regulárních výrazů • http://tutor.fi.muni.cz • úloha Regulární výrazy • 40 příkladů • vyhledávání, nahrazování Náhodnostní imitace vstupního textu • vstup: rozsáhlý text • výstup: náhodně generovaný text, který má „podobné charakteristiky" jako vstupní text • imitace na úrovni písmen nebo slov 39/54 Náhodnostní imitace vstupního textu I špiské to pole kavodali parnas ne nebo kdy v Dejný Odm sem uvalini se zabijí s Pan stěží ře, a silobe lo v ne řečekovících blova v nadrá těly jakvěmutelaji rohnutkohonebout anej Fravinci V A pěk finé houty. zal Jírakočítencej ské žil, kdDo jak a to Lorskříže si tomůžu schno mí, kto. Kterak král kočku kupoval V zemi Taškářů panoval král a zapřísáhl se velikou přísahou že bude pochválena První pán si jí ani nevšimnul zato druhý se rychle shýbl a Juru pohladil Aha řekl sultán a bohatě obdaroval pana Lustiga koupil od něho telegram z Bombaje v Indii není o nic horší člověk nežli někdo z mých hraček Kdepak mávl Vašek rukou 40/54 Základní přístup O vstupní text =>- statistiky textu O statistiky =>- generovaní náhodného textu Co jsou vhodné statistiky? 41/54 Statistiky textu • základ: frekvence písmen (slov) • rozšíření: korelace mezi písmeny (slovy) příklad: pokud poslední písmeno bylo a: • e velmi nepravděpodobné (méně než obvykle) • 1, k hodně pravděpodobná (více než obvykle) 42/54 Implementace • základní frekvenční analýza - datová struktura slovník písmeno =>- frekvence • rozšířená analýza - slovník slovníků písmeno =>- { písmeno =>- frekvence } 43/54 Statistiky jmen • data: četnosti jmen, příjmení podle roků, krajů, ... • zdroj: Ministerstvo vnitra ČR http://www.mvcr.cz/clanek/ četnost-jmen-a-prijmeni-722752.aspx • XLS - pro zpracování v Pythonu uložit jako CSV (comma-separated values) • snadno zpracovatelné, zajímavá data - doporučené cvičení • následuje několik ukázek pro inspiraci ... 44/54 ména vyučujících I Blil - ZDENEK 2020 rvní písmena jmen Prvni pismena 1*940 1950 1960 1970 1980 1990 2000 2010 2020 Rok Identifikace trendů U kterých jmen nejvíce roste/klesá popularita? • co to vlastně znamená? • jak formalizovat? 48/54 Nejdelší růst/pokles Kolik let v řadě roste popularita jména: • Tobiáš - 14 • Viktorie, Ella, Sofie - 9 • Elen, Tobias - 8 Kolik let v řadě klesá popularita jména: • Jana - 26 • Martin - 21 • Petra - 11 • Zdeněk - 9 Největší skok v popularitě za 10 let • alespoň desetinásobný nárůst popularity: Sofie, Elen, Amálie, El la, Nicol, Nella, Tobias • pokles alespoň o 60 %: Petra, Pavlína, Martina Počty používaných jmen Zdroje zajímavých dat Otevřená data / Open data • http://www.opendata.cz • http://www.otevrenadata. • http://www.data.gov/ • http://data.gov.uk/ Zpracování dat seriózněji využití existujících knihoven: • načítání dat ve standardních formátech: HTML, XML, JSON, CSV, ... • operace s daty: numpy, pandas • vizualizace: matplotlib prostředí ipython • regulární výrazy - obecně užitečný nástroj • práce s textem, soubory, daty v Pythonu • příklady • kurzovní lístek • zpracování seznamu studentů • imitace textu • statistiky jmen 54/54