Rychlá analýza dat v iPython notebooku

31. 3. 2014
Doba čtení: 5 minut

Sdílet

Web Státní veterinární správy nabízí jednoduchou mapu s výsledky všech provedených kontrol. Samotná data ale v jednoduše čitelné podobě k dispozici nejsou, takže pokud chcete zjistit, kde toho inspektoři našli nejvíc či jak si vedou podniky ministra financí, musíte se spolehnout na vlastní kousek kódu.

Pro netrpělivé, výsledky jsme v Hospodářských novinách shrnuli do článku Veterinární kontroly: Jak si vede váš řezník. Sběr dat, ale i rozbor jsem prováděl v prostředí iPython notebooku, spuštěném na medium instanci ve službě Microsoft Azure.

Důvody, proč na iHNED.cz používáme Azure, vysvětloval ve svém článku Úložiště v cloudu: porovnání Amazon a Azure kolega Marcel Šulek. Já jen dodám, že tuhle konkrétní úlohu spustíte na libovolné cloudové službě, svém domácím stroji (proč jsem to tak neudělal já, vysvětlím v závěru), případně i na Raspberry Pi.

Linuxová distribuce na analýzu dat

Zmíněný stroj jsem spustil z image Azure Data Analysis, obsahuje mnou obvykle užívané nástroje (Pandas). Nutno dodat, že jsem novinář, ne programátor nebo linuxový admin, možnost celý stroj „naklikat“ mi tak šetří čas i nervy. Návod na rozběhnutí vzdáleného iPython notebooku pak najdete přímo na webu ipython.org.

iPython notebook

Jde o webové vývojové prostředí pro Python, postavené nad interaktivním shellem iPython. Kromě možnosti spouštět kód můžete i vpisovat texty, pokud pak používáte nějaké řešení na tvorbu grafů (Matplotlib), výstupy se zobrazují rovnou na stránce notebooku.

Pokud píšete paralelní kód, iPython notebook vám pomůže nastartovat více procesů (na jednom procesoru nebo napříč clusterem). Jednotlivé projekty (notebooky) jsou uložené jako textové soubory ve formátu .ipynb, takže je velmi snadné je sdílet a spouštět na jiných počítačích. Pro „novinářský“ typ práce je to ideální, čtenáři mohou projekt s minimem práce reprodukovat a ověřit si závěry, které jim předkládáme v článku.

Případně je k dispozici služba nbviewer.ipython.org, která z notebooku vygeneruje statickou HTML stránku.

Stahujeme a zkoumáme

Ale zpět k veterinárním datům. Pokud mapu kontrol propátráte Chrome devtools (Firebugem či jinou alternativou), objevíte skript maps_read_data.php, který metodou POST přijímá rok a typ kontrol (v tržní síti, v bourárnách, mrazírnách…) a vrací JSON seznam všech kontrolovaných subjektů v daném období.

import requests
import json
import pandas as pd

typs = {"01": "Kontroly v tržní síti", "E01": "Kontroly v jatkách na červené maso", "E02": "Kontroly v bourárnách", "E03": "Kontroly v mrazírnách", "E04": "Kontroly v drůbežích porážkách", "E05": "Kontroly v drůbežích porcovnách", "E07": "Kontroly v masných výrobnách", "E08": "Kontroly ve zpracovnách vajec", "E09": "Kontroly v třídírnách a balírnách vajec", "E10": "Kontroly ve zpracovnách ryb", "E11": "Kontroly ve zpracovnách králíků a farm. zvěře", "E12": "Kontroly ve zpracovnách zvěřiny", "E13": "Kontroly v mlékárnách", "P08": "Kontroly ve zpracovnách medu", "KMU": "Kontroly v místech určení (komodity z dovozu)", "P07": "Kontroly přímého prodeje mléka", "E30": "Kontroly ve výr. mlet. a stroj. odděl. masa a polotovarů", "KMUDR13": "MKA - drůbeží maso z dovozu"}
years = ['R2013', 'R2014']
columns = ['E', 'N', 'adresa', 'bod_id', 'cz', 'ddata', 'nazev', 'typ_id', 'zdroj', 'typ', 'rok']

for year in years:
    for typ in typs:
        url = 'http://eagri.cz/public/app/svs_pub/mapy_vk/bin/maps_read_data.php'
        headers = {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', }
        form_data = {'type': 'data_bodu', 'mapa': typ, 'obdobi': year}

        r = requests.post(url,data=form_data, headers=headers)

        rawdata = json.loads(r.text.replace('\ufeff\ufeff',''))
        data = pd.DataFrame(rawdata['rows'])
        data['typ'] = typ
        data['rok'] = year

        master = master.append(data, ignore_index=True)

body = master.bod_id

V druhém kole pak ten samý skript nakrmíme ID bodů a parametrem detail, vrátí se nám všechny pozitivní kontroly i s popisem přešlapu, kterého se ten či onen řezník dopustil. Skript scraperu, stejně jako stažená data (z doby vydání článku) a pracovní kód, kterým jsem získaná data sumarizoval, najdete v našem redakčním GITu.

kontroly = pd.DataFrame(columns=['bod_id', 'nazev', 'popis', 'typ', 'pocet_akci', 'pocet_akci_pozit'])

for bod in body:
    try:
        url = 'http://eagri.cz/public/app/svs_pub/mapy_vk/bin/maps_read_data.php'
        headers = {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', }
        form_data = {'type': 'detail', 'bod_id': bod}
        r = requests.post(url,data=form_data, headers=headers)

        rawdata = json.loads(r.text.replace('\ufeff\ufeff',''))
        if (len(rawdata['rows']) == 0):
            dict = {'bod_id': bod, 'pocet_akci': rawdata['pocet_akci'], 'pocet_akci_pozit': rawdata['pocet_akci_pozit']}
            kontroly = kontroly.append(dict, ignore_index=True)
        else:
            data = pd.DataFrame(rawdata['rows'])
            data['bod_id'] = bod
            data['pocet_akci'] = rawdata['pocet_akci']
            data['pocet_akci_pozit'] = rawdata['pocet_akci_pozit']

            kontroly = kontroly.append(data, ignore_index=True)
    except:
        print('Chyba u ID ' + str(bod))

out = pd.merge(master, kontroly, on='bod_id', how='outer')

out.to_csv('veterina_kontroly_all.csv', sep=';')

Nejdřív jsem zjišťoval, kde toho kontroloři našli nejvíc. Absolutní hodnoty ale bylo třeba dát do kontextu s počtem provozoven. A zatím co 48 nálezů u Novák – maso je sice na pováženou, ale vzhledem k počtu poboček pochopitelné, společnost Enes Fleisch s 38 nálezy a jednou provozovnou si okamžitě získala naši pozornost. Dál jsem zkoumal, jaký typ provozoven trpí závadami nejčastěji a o co obvykle jde (chlazení, úklid, značení, evidence…), což bych doporučil i vám, pokud se budete těmito daty probírat. V funkcemi jako groupby() a agg()  ve výše zmíněném Pandas frameworku jde obvykle o jeden řádek kódu.

A to je všechno? Z pohledu stažení a základního zpracování dat ano, článek samotný vznikal déle, sháněli jsme další informace o vytipovaných firmách, o detailech kontrol, svoje nám řekli i veterinární inspektoři.

ict ve školství 24

Proč vzdáleně?

A na závěr slíbené vysvětlení, proč jsem scrapování i analýzu prováděl ve virtualizované instanci, ne na vlastním stroji. Odpověď není technická, ale procesní: Za cca dvě hodiny běhu Azure medium instance, které jsem nad veterinárními daty strávil, jsem zaplatil necelých 15 korun. Domlouvat se s adminy sítě na instalaci Anaconda distribuce Pythonu, vysvětlovat důvod, čekat na provedení, to vše by vyšlo v lidských nákladech dráž.

A ve chvíli, kdy pracuji s cizími daty (a nenahrávám mimo firemní síť data firmy), žádným způsobem neobcházím bezpečnostní pravidla. Právě možnost vytvářet a mazat malé instance na jednotlivé projekty mi dává možnost experimentovat bez nebezpečí, že si to vyžádá servisní zásah. Jak jsem psal už v úvodu, jsem novinář, ne programátor nebo systémový administrátor, rizika jsou tedy značná.