Hlavní navigace

Rychlá analýza dat v iPython notebooku

Jan Cibulka

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.

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á.

Našli jste v článku chybu?

6. 4. 2014 0:10

Jerzy (neregistrovaný)

Dovolim si zacit statistikoiu. Na každého profesionálního softwarového vývojáře připadají čtyři další bastlici. Lide, kteří nepotrebuji vytvářet robustní aplikace, nepracují na codebase o desítkách tisíc řádku zdrojového kódu a, priznejme si to, obvykle taky nejsou tak dobře placeni. Jedna se o lidi, kteří ač třeba programují denně, jejich programy maji dejme tomu 20 řádku, 100 řádkový program uz je pro ne "velká aplikace". Většina jejich programu pak na konci dne skončí v kosi, obrazně řečeno.<…

1. 4. 2014 0:21

skeptik (neregistrovaný)

"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áž."

Nevím, jestli toto vypovídá o výhodnosti Azure nebo o přebujelé byrokracii ve vaší redakci. ;)

Měšec.cz: mBank cenzuruje, zrušila mFórum

mBank cenzuruje, zrušila mFórum

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Lupa.cz: Kdo pochopí vtip, může jít do ČT vyvíjet weby

Kdo pochopí vtip, může jít do ČT vyvíjet weby

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Vitalia.cz: Spor o mortadelu: podle Lidlu falšovaná nebyla

Spor o mortadelu: podle Lidlu falšovaná nebyla

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

120na80.cz: Jmelí je více léčivé než jedovaté

Jmelí je více léčivé než jedovaté

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: I církev dnes vyrábí potraviny

I církev dnes vyrábí potraviny

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu