Data Quality CZ - portál věnující se tématu kvalitních dat

Unix shell: příručka pro DQM - 1. díl

[1.1.2012] D. Pejčoch

Úvod

Při procházení inzerátů poptávajících DQ analytiky jsem se poměrně často setkal s požadavkem na dobrou znalost programování v prostředí Unix shell. Rozhodl jsem se proto věnovat čas k vytvoření seriálu, který by možnosti využití Unix shell pro řízení datové kvality zmapoval. Vzniklou sérii článků považuji především za studijní materiál pro posluchače kurzu 4IZ562 - Řízení datové kvality, přednášeném na VŠE Praha.

Text je koncipován tak, že vždy nejprve popíši data, na nichž budou jednotlivé příklady využití příkazové řádky demonstrovány. Následně uvedu scénář typických činností pro řízení datové kvality, pro jehož realizaci se poté pokusím nalézt podporu v nástrojích poskytovaných v rámci Unix shell. Každý použitý nástroj bude stručně popsán. Při praktické demonstraci budu postupovat od jednodužších konstrukcí ke složitějším. Text předpokládá rámcové znalosti OS Linux a základní schopnosti práce s příkazovou řádkou.

Popis dat

Představme si firmu, která má dva oddělené provozní systémy. V rámci každého z nich uchovává data klientů. Jednoho dne dostane IT oddělení za úkol klientská data z obou systémů deduplikovat. Za tímto účelem obdrží pověřený pracovník níže uvedené dva datové soubory obsahující základní charakteristiky klientů a adresu jejich trvalého bydliště. Datové soubory jsou ve formátu textového souboru se svislítkem jako oddělovačem.

Tabulka 1: Data ze systému č. 1
Jméno Příjmení Datum narození Počátek kontraktu Ulice Číslo popisné PSČ
David PEJČOCH 12.11.1981 1.1.2011 Hlavní 123 25044
Jan BECHYNĚ 13.3.1956 1.2.2011 Malá 2 35000
Vítek NEZNÁLEK 2.4.1981 4.5.2010 Nízká 23 45000
Fero CHALAPENOS 23.12.1976 1.1.2011 Strmá tř. 24 34000
Tabulka 2: Data ze systému č. 2
Jméno Příjmení Datum narození Počátek kontraktu Ulice Číslo popisné PSČ
Ján Bechyně 13.3.1956 2.5.2011 Malá 2/14 35001
Fero Chalapegnos 23.12.1976 3.6.2011 Strmá ul. 24 34000

Scénář deduplikace

Na první pohled je zřejmé, že klienti ze druhého souboru jsou zřejmě duplicitní k těm ze souboru prvního. Jejich jména, resp. příjmení obsahují jen drobné odchylky od 1. souboru, způsobené nejspíše chybou při typování (Jan vs. Ján, Chalapegnos vs. Chalapenos). Rovněž adresy jejich trvalého bydliště se na první pohled zdají být shodné, až na drobné rozdíly (drobná chyba v názvu ulice, číslo orientační vložené do atributu pro číslo popisné, přesnější varianta PSČ v druhém souboru). Při ruční deduplikaci bychom tak bez dodatečných informací sloučili oba klienty z druhého souboru s těmi ze souboru č. 1. Pouze bychom zřejmě starší údaje (určené datem počátku kontraktu) přepsali těmi novějšími (s výjimkou čísla popisného u Jána Bechyněho). Jak ale postupovat v případě, kdyby soubory čítaly statisíce záznamů?

Scénář konkrétních činností by mohl vypadat takto:

  1. Sloučení souborů z více zdrojů do jediného;
  2. Přidělení unikátního identifikátoru pro každý řádek;
  3. Vytvoření pracovní kopie souboru v rámci níž budou prováděny úpravy;
  4. Unifikace velikosti písmen;
  5. Standardizace názvu ulic / náměstí v adrese;
  6. Náhrada možných překlepů;
  7. Identifikace duplicit a vytvoření „master“ záznamů.

Sloučení souborů do jednoho

Pro slučování souborů je možné snadno použit příkaz cat. Před sloučením se však budeme potřebovat zbavit hlavičky s názvy atributů v připojovaném souboru. Docílíme toho aplikací příkazu tail. Příkaz tail +2 soubor2 > proxy načte všechny řádky od 2. (tedy přeskočí hlavičku) a výstup přesměruje do souboru proxy. Nyní je možné pomocí příkazu cat soubor1 proxy > joined oba soubory sloučit do jediného souboru pojmenovaného joined.

Přidělení unikátního identifikátoru pro každý řádek

Příkaz nl umožňuje každému řádku v rámci textového souboru přidělit jedinečný identifikátor. Konkrétním příkazem nl -v 1 -i 1 -s\| -n rn joined > proxy docílíme přiřazení numerického klíče, který bude začínat číslem 1 (parametr -v) a bude s každým řádkem inkrementálně zvyšován o 1 (parametr -i). Od ostatních atributů bude oddělen svislítkem (parametr -s) a bude zarovnán vpravo bez úvodních mezer (parametr -n). Výsledek bude přesměrován do souboru proxy. Vytvoření pracovní kopie souboru v rámci níž budou prováděny úpravy Příkazem cp proxy joined zkopírujeme souboru proxy tak, že jím přepíšeme původní soubor joined. Zůstane nám tak zachována kopie sjednocených dat s přiděleným klíčem pomocí něhož na závěr navážeme zmodifikovaná data.

Unifikace velikosti písmen

Přesto, že některé dále použité příkazy umožňují nastavit své parametry tak, aby ignorovaly rozdíly ve velikosti písmen, je účelné ukázat, jak téhož dosáhnout pomocí příkazu tr. Aplikací příkazu cat joined | tr „[:lower:]“ „[:upper:]“ > proxy nebo alternativně cat joined | tr „a-z“ „A-Z“ docílíme téhož; záměny malých písmen na velká. Bohužel si však tento příkaz neporadí s diakritikou. Všechna písmena s diakritikou zůstanou malá. Za této situace si lze pomoci opět příkazem tr, tentokráte s taxativním vymezením písmen, která mají být zaměněna: cat proxy | tr „ěščřžýáíéůúóďťň“ „ĚŠČŘŽÝÁÍÉŮÚÓĎŤŇ“ > cleaned. Výsledek je uložen v souboru cleaned.

Standardizace názvu ulic / náměstí v adrese

Standardizací se obecně rozumí sjednocení variant, v nichž lze daný pojem zapsat. V případě názvů ulic je to např. sjednocení variant „Ul.“, „Ulice“, „Tř.“, „Třída“, „Nám.“, „Náměstí“, „N.“, apod. Standardizace je prováděna aplikací tzv. standardizačního schématu mapujícího na sebe původní hodnoty a hodnoty standardizované. K tomuto účelu je možné použít např. nástroj sed. Příkazem sed –i ‘s/\ TŘ./\ UL./g‘ cleaned docílíme záměny všech řetězců „ TŘ.“ na „ UL.“ v souboru cleaned.

Aplikací příkazu sed jsme provedli záměnu v rámci celého souboru. Mnohem častěji tak budeme chtít učinit v rámci jednoho nebo více atributů. Postupovat můžeme tak, že nejprve pomocí nástroje awk do separátního souboru odfiltrujeme atributy, u nichž chceme standardizaci shodným schématem provést a poté je zpět navážeme příkazem join. Konkrétně příkazem awk –F \| ‚{print $1“|“$6}‘ cleaned > std_ulice do souboru std_ulice extrahujeme první (klíč) a šestý atribut (ulice). Parametrem -F říkáme awk, že oddělovačem jednotlivých atributů je svislítko. Jelikož by mohlo být interpretováno jako přesměrování výstupu, je nutné svislítko uvést zpětným lomítkem.

Zpět lze navázat změněný atribut pomocí zmiňovaného příkazu join, který lze chápat jako implementaci databázového inner join pro textové dokumenty. Konkrétním příkazem join –t \| cleaned std_ulice > proxy navážeme přes první atribut (klíč) soubory std_ulice a cleaned. Výstup přepíše soubor proxy. Parametrem –t definujeme svislítko jako oddělovač jednotlivých atributů.

Náhrada možných překlepů

K náhradě překlepů lze opět použít příkaz tr. V případě nutnosti náhrady řetězců o více písmenech je vhodné použít nástroj sed nebo awk. Příkaz awk ‚{if ($2 == „JÁN“) $2 = „JAN“; print;}‘ proxy > cleaned nahradí řetězec „JÁN“ v rámci druhého atributu (jméno) řetězcem „JAN“. Kompletní obsah souboru proxy uloží po transformaci do souboru cleaned. Příkazem sed –i ‚s/GN/N/g‘ na příjmení extrahované do separátního souboru je možné aplikovat standardizační pravidlo umožňující eliminaci chybného zápisu některých příjmení, v našem případě „Chalapegnos“ vs. „Chalapenos“.

Identifikace duplicit a vytvoření „master“ záznamů

V případě, že máme k dispozici standardizované záznamy pro všechny atributy, podle nichž budeme hledat možné duplicity, je na tyto atributy možné aplikovat příkaz uniq. Před vlastní aplikací je ale vhodné jednak extrahovat atributy, podle nichž bude probíhat hledání shody do zvláštního souboru a jednak je nutné změnit oddělovače mezi atributy, jelikož příkaz uniq uvažuje pouze mezeru nebo tabelátor. Pro záměnu oddělovačů je opět možné použít příkaz sed. Konkrétně příkaz sed –i ‚s/|/\ /g‘ soubor nahradí svislítko jako oddělovač mezerou. Vlastní deduplikaci provedeme příkazem sort –k 2,5 cleaned | uniq –f 1 –c > master. Příkazem sort setřídíme soubor podle rozmezí klíčů definovaného parametrem –k . Výstup přesměrujeme do příkazu uniq, který na základě parametru –f ignoruje při hledání shody první atribut představující klíč a na základě parametru –c k jednotlivým master záznamům přidává četnosti jejich výskytu.

Jelikož pro výběr master záznamu chceme použít ten nejmladší, je nutné ještě přidat do příkazu sort parametr, který pozmění pro vybraný atribut směr řazení. Pokud řadíme záznamy podle prvních třech atributů (jméno, příjmení, datum narození) vzestupně a podle čtvrtého (datum kontraktu) sestupně, svůj účel splní příkaz: sort +0 -3 4r -4

Závěr

V rámci prvního dílu seriálu o využití Unix shell pro úlohy v rámci řízení datové kvality jsme se seznámili se základními nástroji, které lze použít. V příštím díle tuto paletu ještě rozšíříme a přejdeme k pokročilejším technikám.

Komentáře ke článku

Stránka byla naposledy aktualizována dne 4.5.2015
Powered by HOLOPAGE
©2011 - 2015 D. Pejčoch