Jestem jedną z tych osób, które uważają, wykresy kołowe to najgorszy możliwy sposób prezentacji danych.

Jakiś czas temu Maciej B. przesłał mi link do raportu, który zachwiał tym przekonaniem.

Raport o wdzięcznym tytule ,,Analytics: The real-world use of big data” opracowany przez IBM Institute for Business Value zawiera wykresy kwadratowe. Oto jeden z nich:

Jaki morał wyciągnąłem z tego raportu?
Big Data przełamie jeszcze niejedną barierę.


Czasem próba zmierzenia się z (na pozór) niewinnym pytaniem, prowadzi do bardzo interesujących rozwiązań. Myślę, że dzisiejszy gościnny wpis Michała Kurtysa, będzie tego świetnym przykładem. Aby dowiedzieć się ile samorządy wydają na transport publiczny będziemy musieli zmierzyć się z narzędziami do digitalizacji pdf’ów, rozpoznawania tekstu oraz parsowania tabel. Będzie technicznie, będzie ciekawie.

Ile pieniędzy samorządy wydają na transport publiczny?
Jak wyekstraktować informacje z plików PDF, które zawierają dane w postaci obrazków?
Budżety samorządów.

Michał Kurtys

Ile pieniędzy wydaje moje miasto na transport publiczny? Czy to dużo?
Kiedyś zasłyszałem, że istotnie niemało. Zajrzałem zatem do budżetu miasta na rok 2013.
Wartość bezwzględna tej liczby wydała się faktycznie odpowiadać tej opinii.
Nie znam się jednak na transporcie. Ta kwota, choć spora, mogła być niezbędna. Postanowiłem zobaczyć więc, jak to wygląda na tle innych miejscowości.
Oczywiście odnosząc się do innych miejscowości w dalszym ciągu nie będzie to dokładne porównanie, chociażby z uwagi na różny stan taboru czy cenę biletów, ale zawsze jest to jakiś punkt odniesienia.

W dalszym ciągu zagadnienie transportu publicznego będzie służyło jako przykład.
Doszliśmy do momentu w którym interesować nas będzie ogólny problem zgromadzenia danych z budżetów samorządów.

Budżety zazwyczaj znajdziemy w biuletynie informacji publicznej danego samorządu, samorząd musi takie informacje publikować. Znalazłem stronę na której są odnośniki do BIP-ów poszczególnych jednostek samorządowych (http://www.bip.gov.pl/subjects/index/4600).

Teoretycznie wystarczyłoby wybrać interesujące nas podmioty (np. rady miast w województwie dolnośląskim).
Następnie dla każdego BIP-a odpalić crawler, który znalazłby dla nas ustawę budżetową.
Sam pisałem taki program w pythonie korzystając z biblioteki Scrapy.
Niestety bez rezultatów. Strony są bardzo zróżnicowane i trudno znaleźć odpowiednią regułę dla poszukiwań.

Sytuację trochę (za chwilę okaże się, że nie całkowicie) ratuje dziennik ustaw.
Dla woj. dolnośląskiego znajduje się pod adresem http://edzienniki.duw.pl/duw/ActByMonthYear.aspx#.

Znajdziemy tam ustawy uchwalone przez samorządy terytorialne, wśród nich oczywiście ustawy budżetowe.
Zacząłem od pobrania wszystkich ustaw z roku 2013. Tym razem nie użyłem biblioteki Scrapy.
Strona ładuje zawartość tabeli w sposób dynamiczny i znacznie wygodniej było skorzystać z biblioteki Selenium.
Skrypt do odczytywania danych z użyciem tej biblioteki można znaleźć tutaj. Nie jest napisany najpiękniej ale działa. [dzcrawler.py]

Następnie wybrałem te ustawy, które:

  • zostały uchwalone przez radę miejską lub radę miasta i gminy
  • dotyczyły uchwały budżetowej
  • nie dotyczyły zmian budżetu

Lista ustaw: [miasta2013.csv]

Interesujące mnie dokumenty pobrałem za pomocą prostego skryptu i programu wget. [downloader.py]

Przyglądając się jednak tym, co udało się pobrać, zostałem niemile zaskoczony niekompletnością listy budżetów.
Przykładowo w pobranych plikach brakuje budżetu dla miasta Lubin. W biuletynie informacji publicznej znajdziemy ją wśród uchwał z dnia 26 lutego 2013.
http://www.bip.um-lubin.dolnyslask.pl/dokument.php?iddok=2449&idmp=49&r=o

Dla tego dnia w dzienniku znajdziemy tylko jeden dokument:

Rada Miejska w Lubinie	Uchwała	2013-02-26 	2013-04-24 	uchwała nr XXXIV/261/13 Rady Miejskiej w Lubinie z dnia 26 lutego 2013r. w sprawie Regulaminu utrzymania czystości i porządku na terenie Gminy Miejskiej Lubin.

Nie wiem dlaczego w dzienniku nie ma wszystkich uchwał.
Co gorsza nie są to pojedyncze przypadki.
W dalszej części będziemy po prostu pracować z mniejszym zbiorem.
Brakujące dokumenty można oczywiście znaleźć i pobrać ręcznie.
Mając w planach automatyzację analiz dla całego kraju, jestem trochę zawiedziony brakiem kompletności i automatyzowalności procesu pozyskiwania budżetów z BIP.

Przyjrzyjmy się ściągniętym danym. Wszystkie ustawy są zapisane w formacie PDF.
Większość dokumentów ma podobną strukturę. Zawierają przede wszystkim bardzo dużo tabel.
Bardzo cieszy fakt, że w prawie każdym dokumencie, znajdziemy tabele, które są niemal identyczne. [patrz rys. 1 ]. Jeszcze bardziej, że jest to pewne podsumowanie. Jeżeli chodzi o problem transportu, to jest w nich wszystko czego potrzebujemy i wszystkie inne moglibyśmy zignorować.

I tu znajdują się wyjątki od reguły. Część dokumentów ma zupełnie oryginalną strukturę np. Wrocław.
Dla każdego takiego przypadku należałoby implementować zmodyfikowany algorytm.
Zajmiemy się zatem tylko większością.

Jak wspomniałem interesujące nas dane są zapisane w tabelach.
Te zaś w praktycznie każdym przypadku są obrazami umieszczonymi w dokumencie, co oznacza, że aby wyciągnąć z dokumentu liczby należy użyć jakiejś biblioteki do rozpoznawania tekstu.
W tym projekcie użyłem silnika Tesseract. Program ten został stworzony przez firmę HP, w 2005 roku jego kod został uwolniony, a teraz jego rozwój sponsoruje Google.
W tej chwili prawdopodobnie jest najlepszym opensourcowym silnikiem OCR. Co ważne w aktualnej wersji potrafi również rozpoznawać język polski bez dodatkowego treningu.
Tesseract udostępnia interfejs dostępny z poziomu linii komend oraz API programisty.
Istnieją również graficzne frontendy zarówno dla systemów Windows jak i Linux.

Zanim jednak odpalimy tesseract potrzebujemy przekonwertować dokument do postaci pliku graficznego takiego jak .png czy .jpg.
Można do tego użyć programu convert z pakietu ImageMagick (wymaga zainstalowanego GhostScripta).
Renderuje on każdą stronę dokumentu z określoną przez użytkownika rozdzielczością (w dpi).

convert -density 600 plik.pdf  obraz%d.png

Alternatywą jest użycie pdfimages (poppler-utils), który po prostu wyciąga wszystkie obrazy z pliku PDF.
W tym przypadku jest to lepsza droga – otrzymujemy faktycznie to czego potrzeba, a i obrazy na pewno będą mieć oryginalną rozdzielczość.

Z nieznanych mi przyczyn odczytując budżet Lwówka Śląskiego zarówno convert jak i pdfimages wpadały w nieskończoną pętlę. Sytuacja na szczęście nie powtórzyła się dla innych miast. Po odczytaniu każdego dokumentu otrzymujemy katalogi z plikami graficznymi.
Oczywiście nie wszystkie z nich przedstawiają tabelę. Zwykle jednak nie-tabele to pojedyncze obrazki. Nawet nie usuwałem ich, po prostu po skanowaniu dadzą pusty wynik.

W obecnej wersji tesseract nie radzi sobie ze złożonym układem graficznym strony z tekstem.
Nie możemy uruchomić tesseracta bezpośrednio na pliku graficznym z tabelą. W wyniku dostalibyśmy po prostu mnóstwo śmieci.

Aby temu zaradzić wytniemy każde pole tabeli i przekażemy je do tesseracta.
Zanim pokażę jak podzielić tabelę, chciałbym poruszyć jeszcze jedną kwestię.

Gdy sam wdrożyłem powyższy pomysł w życie, spotkała mnie niemiła niespodzianka. Rezultat był raczej średnio zadowalający – bardzo często występowały “literówki”.
Kiedy spojrzymy w powiększeniu na tekst zobaczymy, że jest lekko rozmyty. Próbowałem różnych filtrów by poprawić jakość, ale bez większego skutku.
Tesseract pracuje wyłącznie na binarnych obrazach (jeżeli dostaje obraz nie-binarny przeprowadza binaryzację). Pomyślałem więc, że może dla antyaliasowanego tekstu warto byłoby napisać własny silnik?
Poruszyłem ten temat na stackoverflow: http://stackoverflow.com/questions/21827854/ocr-on-antialiased-text
Rozwiązanie było trywialne. Tekst był renderowany z użyciem technologii ClearType, dzięki której tekst wygląda lepiej na ekranach LCD.
Działanie polega na sprytnym “zwiększeniu rozdzielczości” wyświetlacza poprzez wykorzystanie horyzontalnego ustawienia subpixeli.
Wiedząc o tym rozbijamy każdy piksel na 3 subpiksele i zapisujemy ich wartość w odcieniach szarości.
Otrzymamy więc obraz o 3x większej poziomej rozdzielczości niż wejściowy. A to wystarczy, żeby OCR działał jak trzeba.
Jeżeli Czytelnik zainteresowany jest szczegółami to polecam wątek w stackoverflow, czy chociażby artykuł w wikipedii.
Przykładowy kod w pythonie i opencv dokonujący tą operację: [unsubpixel.py]

Teraz możemy wrócić do problemu formatu tabeli. Tabele jak zauważyliśmy nie są skanowane, a renderowane w jakimś programie. Oznacza to, że mamy ułatwione zadanie, ponieważ wszystkie linie są idealnie pionowe lub poziome
Pierwszym krokiem jest zatem znalezienie wszystkich odpowiednio długich linii pionowych i poziomych.
Tak znalezione linie nanosimy na czysty obraz, dostając “szkielet” tabeli (+ w rzadkich przypadkach drobne śmieci).

Teraz wystarczy znaleźć punkty przecięcia linii i wyznaczyć odpowiednie pola.
W bibliotece opencv możemy jednak ułatwić sobie zadanie wykorzystując funkcję findContours.
http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#cv.FindContours
Mając dany obraz binarny funkcja ta znajduje kontury obiektów.
Ponadto zwraca również hierarchiczną strukturę kształtów w obrazie. Najlepiej zobaczymy to tutaj:

Obraz pochodzi z dokumentacji opencv:
http://docs.opencv.org/trunk/doc/py_tutorials/py_imgproc/py_contours/py_contours_hierarchy/py_contours_hierarchy.html#contours-hierarchy

Biorąc obiekty na samym dnie hierarchii otrzymamy najbardziej wewnętrzne kształty, czyli pola tablicy.

    vector > contours;
    vector hierarchy;

    Mat lines_img_cpy = lines_img.clone();
    findContours(lines_img_cpy,contours_all, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
    
    for( unsigned int i=0; i< hierarchy.size(); i++)
    {
        if( hierarchy[i][2]==-1 )
            contours.push_back(contours[i]);
    }

///////////////////////////////////////////////
Tesseract dostarcza również całkiem wygodne api
///////////////////////////////////////////////

    tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
	if (api->Init(NULL, "pol")) {
        fprintf(stderr, "Could not initialize tesseract.\n");
        //exit(1);
        return results;
    }

    for (unsigned int i = 0; i < contours.size(); i++)
    {
         int minx = img.cols;
         int maxx = 0;
         int miny = img.rows;
         int maxy = 0;
        for (unsigned int j = 0; j < contours[i].size(); j++)
        {
            minx = min(minx,contours[i][j].x);
            maxx = max(maxx,contours[i][j].x);

            miny = min(miny, contours[i][j].y);
            maxy = max(maxy, contours[i][j].y);

        }
        Mat subimg = img(Range(miny, maxy), Range(minx, maxx));
        api->SetImage(subimg.data, subimg.cols, subimg.rows, 1, img.cols);
        outText = api->GetUTF8Text();
        results.push_back(outText);
		//////////////

Ostatnią rzeczą, którą należy zrobić to uporządkowanie wyników, które dostaliśmy.
Tutaj “idealność” renderowanej tabeli znowu upraszcza sprawę.
Kontury o tej samej współrzędnej y będą tworzyły jeden wiersz.
Trochę inaczej jest w nagłówkach, ponieważ mają one wielopoziomową strukturę.
Gdy jeszcze raz spojrzymy na przykładową tabelę, możemy zauważyć, że w ostatnim wierszu nagłówków szerokości pól są identyczne jak w pierwszym wierszu danych.
To całkiem dobra heurystyka do oddzielenia danych od nagłówków.

Warto wiedzieć które kolumny to przychody, a które koszty.
Aby nie stracić informacji. Przejdziemy po nagłówkach w dół jak po drzewie.
Kolejne kolumny nazwiemy więc:

"LP'  "
"Dz.  "
"Rozdz.  "
"Nazwa  "
"Stan srodkow obrotowych na początek  roku  "	
"Przychody /ogółem  "
"Przychody/w tym dotacja przedmiotowa /Kwota  "
"Przychody  /w tym dotacja przedmiotowa  /zakres dotacji  "
"dotacja celowa inwestycyjna /Kwota  "	

i tak dalej.
Dla każdej tablicy tworzymy dwa pliki wyjściowe:
Jeden zawierający współrzędne pola i jego zawartość.
W drugim wyniki zawierające zapisane wierszami.

Wyniki:
Z powodu wszystkich trudności, które wymieniłem w artykule, ostateczna baza miast jest bardzo skromna.
Oczywiście, część z problemów jest do przeskoczenia. Na pewno przetworzenie plików o “specjalnej” strukturze

Transport:
Skorzystamy z tego, że w pliku zawsze istnieje podsumowująca tabela o w miarę niezmiennym kształcie.
W skrypcie przeszukujemy wyniki skanowania tabel o ilości kolumn równej 16,17 lub 18.
Jeżeli znajdziemy identyfikator Transportu Lokalnego równy “60004″, to wypisujemy wartość wydatków na ten cel.

Koniec końców udało się wyciągnąć wielkość wydatków na transport lokalny w różnych miastach województwa dolnośląskiego.

python.exe list_big.py
Bolesławiec-007_table.txt 3 280 000
Dzierżoniowa-006_table.txt 1 850 000
Kątach-025_table.txt 460 000,00
Oławie-015_table.txt 900 000
Piławie-005_table.txt 250 000
Zgorzelec-029_table.txt 290 000
Złotym-012_table.txt 3 000.00
Świdnicy-014_table.txt 8 636 090
Świebodzicach-008_table.txt 823315

Pod adresem www.biecek.pl/Eseje/indexObraz.html udostępniliśmy esej o tytule ,,Percepcja obrazu”, drugi z serii ,,Wakacje z wizualizacją”.

Można się z niego dowiedzieć w jaki sposób obraz jest przetwarzany na drodze: przedmiot na który patrzymy – mózg. A jak się okazuje się dzieje, dużo. Zobaczcie sami.

Jako zachętę do przeczytania całości, poniżej prezentujemy fragment opracowany przez Karolinę Biecek (czytaj: panią prezes). Mamy też konkurs w którym można wygrać papierową wersję całego zbioru esejów! Aby wziąć udział w konkursie należy wymyślić interesujące zadanie, które weryfikuje wiedzę przedstawioną w eseju o percepcji obrazu i przesłać mi opis tego zadania pocztą na adres Przemyslaw.Biecek na serwerze gmail.com do 26 lipca 2014 (z dopiskiem w tytule maila ‘Konkurs’).


Co łączy dentystę i dietetyka?

Karolina Biecek

O czym myślicie podczas wizyty u dentysty? Wolicie myśleć w tym momencie o swoich właśnie leczonych zębach czy o czymś zupełnie innym?
Może następnym razem pomyślicie o tzw. iluzji dentystycznej? Dentyści, jak i my wszyscy, ulegają złudzeniom optycznym, w ich przypadku złudzenie to ma niestety takie konsekwencje, że czasem wiercą zbyt duże dziury w zębach swoich pacjentów (czyli w naszych).


Co to znaczy? Wyobraźmy sobie, że jesteśmy dentystą i widzimy takie dwie dziury w zębie jak na obrazku po prawej. Która jest większa? Którą należy bardziej oczyścić (czyli w rozumieniu laika dentystycznego, rozwiercić?). Wygląda na to, że prawa dziura jest olbrzymia, zatem należy ją mocniej rozwiercić.

Tymczasem obie czarne „dziury” są jednakowe. Jest to właśnie iluzja dentystyczna, a tak naprawdę iluzja Delboeufa (Delboeuf Illusion), która polega na tym, że gdy dwie jednakowe ciemne okręgi otoczymy kołami o wspólnym środku, to okrąg otoczony kołem o mniejszym promieniu wyda się większy. Czyli, gdy wewnętrzne koło jest znacząco mniejsze niż zewnętrzne, to wydaje się jeszcze mniejsze. Natomiast, gdy wewnętrzne koło jest nieznacznie mniejsze niż zewnętrzne, to wydaje się większe niż jest w rzeczywistości.

Iluzja Delboeufa ma również duże znaczenie dla wszystkich odchudzających się, zatem warto, aby znali ją też dietetycy. Jeżeli ktoś się odchudza i położy sobie jedzenie na mniejszym talerzu, to będzie mu się wydawało, że zjadł więcej zatem dłużej będzie czuł się syty – bowiem wierzymy w to, co widzimy – w konsekwencji zje mniej, będzie mniej podjadał.
Jednak, jest to obwarowane pewnymi dodatkowymi warunkami. Warto zadbać o zastawę w kolorach kontrastujących z obrusem, wtedy iluzja będzie dobrze widoczna. Jednocześnie powinniśmy nałożyć na talerz jedzenie w wyraźnym kolorze. Polecany jest np. mały jasny talerz, ciemny obrus i ciemne jedzenie. W przypadku jedzenia w kolorze zbliżonym do talerza nasz mózg musi się bardziej napracować, aby ocenić wielkość porcji i powiedzieć nam „dosyć”.
Najlepsze w tym jest to, że mimo tego, że wiemy, że mamy mały talerz, to nasz mózg i tak ulega tej iluzji.

Dodatkowo odchudzającym się pomaga iluzja T, czyli iluzja polegająca na tym, że nasz mózg przeszacowuje rozmiar pionowy w porównaniu z poziomym. Czyli używając wąskich szklanek wlejemy sobie mniej napoju – co jest istotne, jeżeli pijemy napoje kaloryczne. Natomiast, gdy idziemy do baru – jeżeli dostaniemy szeroką szklankę to prawdopodobnie dostaniemy też więcej płynu ;)


Ten esej to część zbioru ,,Odkrywać! Ujawniać! Objaśniać!” wydanego przez Fundację, dostępnego już w przedsprzedaży. O tym jak go kupić można przeczytać na stronie http://biecek.pl/Eseje/indexZakup.html. Co trzy tygodnie na stronie http://biecek.pl/Eseje/ będziemy publikować kolejny rozdział w postaci elektronicznej, bezpłatnie, na otwartej licencji CC BY&SA.

Iluzja Titchenera

8 lip
2014

Za dwa dni odkrywamy Esej o percepcji obrazu.

Na rozgrzewkę mały konkurs, można wygrać kubek.

Drugi esej będzie o tym jak postrzegamy obraz oraz o problemach z percepcją obrazu.
Świetną ilustracją problemów z percepcją są iluzje. Przykład iluzji Titchenera przedstawiamy obok. Trudno uwierzyć, że środkowe koła są równej wielkości, prawda?

Zadanie: Znaleźć wykres (i wkleić link do niego w komentarzu), w którym element wykresu z uwagi na elementy sąsiednie wydaje się większym, lub mniejszym, niż w rzeczywistości. Wygrywa najciekawszy przykład. Czas na zgłoszenia: do czwartku.


Wczoraj zakończyła się konferencja useR, poniżej wkleję kilka linków do tematów, które najbardziej mnie zainteresowały. Wyraźnie widać przesunięcie akcentów na technologię w useR’ach w Ameryce i na matematykę w useR’ach w Europie. W tej edycji udział wzięło około 700 osób, kolejna konferencja useR!2015 będzie w Danii.

Ciekawy był referat Johna Chambersa, dotyczący interfejsów i dużych danych. Swoista odpowiedź dla tych narzekających, że pewnych rzeczy w R zrobić nie można tak szybko jak w innych językach (np. wywołanie funkcji to koszt około 10^3 operacji a data.frame są nieustannie kopiowane). Podał trzy projekty Rcpp11, Rllvm i h2o które umożliwiają zanurzenie w R kodu bibliotek napisanych w innych językach.

Bardzo ciekawy był referat o ggvis, projekcie łatwego tworzenia interaktywnych wykresów (kombinacja ggplot, shiny, dplyr i vega.js). Konkurencja dla interaktywnych wykresów, np rCharts ma tę wadę, że jest jedynie zbiorem (fajnych) szablonów, a ggvis to gramatyka. Poza tym połączenie shiny, markdown i ggplota pojawiało się w kilku referatach o systemach raportujących.

Urzekające było gdy przy prezentacji plot.ly (narzędzie do współdzielonej pracy nad wykresami) użyto do prezentacji wyników z polskiej matury 2013 (ten rozkład robi wrażenie).

DE przedstawił platformę docker, która wydaje się być genialnym narzędziem do testów kodu pomiędzy platformami.

Przez wiele referatów przewijała się biblioteka leaflet do tworzenia interaktywnych map.

Przedstawiono ‘easter egg’w R, aby zobaczyć jak działa trzeba wpisać poniższe trzy linijki do R
Anybody ? there ???
?
''

JF pokazał nowe funkcje w bibliotece effects, do wizualizacji efektów w modelach regresyjnych.

Spodobał mi się pakiet scagnostic do diagnostyki scatterplotów.


Dziś miały miejsce tutoriale na useR 2014. Materiały pomocnicze, kody i slajdy można pobrać ze strony http://user2014.stat.ucla.edu/#tutorials. Poniżej opiszę wrażenia z dwóch tutoriali w których byłem udział.

Rano wybrałem ,,Applied Spatial Data Analysis with R” skuszony materiałami, które są streszczeniem książki autora warsztatów Virgilio Rubio. Niestety o ile materiały są przydatne, o tyle warsztaty były przykładem próby pokazania 320 slajdów (nie przesadzam, specjalnie policzyłem) w 3 godziny, przy okazji przelatując przez pięć różnych przykładowych danych i kilkanaście modeli. Gdyby to jeszcze były slajdy z obrazkami, ale na wielu z nich były poważne wzory.

Po południu wybrałem (drogą eliminacji) dplyr prezentowany przez Hadley Wickhama i to był świetny wybór. Hadley zdążył ,,przerobić” 60 slajdów ale w taki sposób, że się można było czegoś nauczyć. Jeden ciekawy przykładowy zbiór danych pozwalał na przećwiczeniu ze zrozumieniem większości z przedstawianych tricków. Zabawki w stylu operatora pipeline ‘%>%’ (dlaczego tego nie było wcześniej?), tłumaczenia składni dplyra na SQL (można teraz pracować na NAPRAWDĘ dużych danych), joiny oraz funkcje działające w oknach (wreszcie merdże i operacje w grupach zrobione są porządnie) to wszystko co dało się w zagmatwany sposób zrobić też wcześniej, ale teraz wreszcie można zrobić to z przyjemnością.
Gorąco polecam materiały z tego tutoriala.


Wonder how submissions to the DataVis contest at useR!2014 (see contest webpage) look like?

There are 8 submissions in the track 1 (schools matter) and 10 submissions in the track 2 (inequalities in academic achievement).

You can see all submissions (with correspoing R codes) on this webpage.


Marcin Koralewski przygotował krótką relację z IV Niezależnych Ogólnopolskich Mistrzostw w Analizie Danych. Poniżej umieszczamy i relacje i treści finałowych zadań.
[zdjęcie po prawej pochodzi z albumu zawodów NOMAD]


Dnia 7 czerwca odbył się finał IV Niezależnych Ogólnopolskich Mistrzostw w Analizie Danych, tym samym dając kres kilkumiesięcznej wytężonej pracy członków Koła Naukowego Statystyki Matematycznej “Gauss”. Finaliści mierzyli się z zadaniami w dwóch kategoriach wiekowych: szkół ponadgimnazjalnych oraz studentów. Mistrzostwa mają na celu propagowanie statystyki jako dziedziny matematyki obecnej na co dzień w ludzkim życiu, przy wykorzystaniu programowania np. w R. I o ile zadania dla szkół ponadgimnazjalnych są zazwyczaj deterministyczne i opierają się na rachunku prawdopodobieństwa, to zarówno oni, jak i studenci muszą mierzyć się z nietrywialnymi problemami (z których czasami najbardziej niemożliwym do sforsowania jest przebrnięcie przez treść zadania).

W tym roku zwycięstwo w kategorii liceów przypadło Piotrowi Przestrzelskiemu oraz Erykowi Kijewskiemu z Suwałk, zaś w kategorii Szkół Wyższych Pawłowi Budzianowskiemu oraz Tomaszowi Stroińskiemu z UAM’u.
Szczególne gratulacje należą się zwycięskiej drużynie licealistów- jest to pierwsza drużyna w dziejach konkursu, która rozwiązała wszystkie 5 zadań, i to w zatrważającym tempie niecałych 2,5 godziny!

Dzięki hojności sponsorów, w tym Fundacji SmarterPoland, wszystkich udało się szczodrze nagrodzić.
Czytelników zachęcamy do zapoznania się z zadaniami, oraz spróbowania swoich sił przy ich rozwiązywaniu- ci zaś, którzy nie ukończyli jeszcze studiów, będą mieli okazję już w maju przyszłego roku ponownie stanąć w szranki z hobbystami statystyki z całego kraju :) Szczególnie polecam zapoznać się z studenckim zadaniem FP2, o psującej się maszynie- sprawiło ono finalistom dość dużo problemów.

Zadania 1
Zadania 2


Mając w pamięci poprzednią książkę Nassima Taleba, czyli sławną ,,Black Swan” moje oczekiwania w stosunku do jego kolejnej książki ,,Antykruchości” były bardzo wysokie. Jakie są więc wrażenia z lektury tej pozycji?

Początek jest świetny. Autor zręcznie wyjaśnia czym jest tytułowa antykruchość. A czym jest? Oczywiście przeciwieństwem kruchości, ale jednocześnie jest przeciwieństwem którego się nie spodziewamy. Dla większości osób przeciwieństwem kruchości jest odporność. Przyzwyczajeni jesteśmy do myślenia w granicach odporność – kruchość i nie widzimy, że jest coś poza tymi granicami. Jeżeli kruchość oznacza, że duże zmiany pogarszaj/psują, to antykruchość oznacza, że duże zmiany poprawiają/usprawniają system. W statystyce odpowiedzią na wrażliwe i niestabilne estymatory są estymatory odporne. Ale teraz można zapytać się, czy istnieją estymatory antykruche? Którym skrajne obserwacje jedynie służą? Czy można i co można zrobić, by nasze wnioskowanie było antykruche? Pod względem poszerzania perspektywy początek jest świetny.

Środek jest niezły. Autor na ilustracjach wykazuje potencjalne źródła kruchości, takie jak wielkość i złożoność systemów. Punktuje zachłyśnięcie się złożonymi modelami predykcyjnymi, za którymi nie idzie żadna odpowiedzialność w przypadku błędnych predykcji. Pokazuje jak często stosowane miary jakości predykcji są błędne, a same systemy predykcyjne nie tylko niczego nie przewidują, ale mogą być wręcz szkodliwe tworząc złudzenie kontroli niepewności. Im bardziej złożone, tym bardziej niezrozumiałe i kruche.

Na poletku analizy danych ta diagnoza jest wyjątkowo trafna. Coraz więcej osób buduje złożone modele, wierząc że dzięki złożoności będą mogli lepiej przewidzieć pewne zjawiska. Jednocześnie nie zadając sobie pytań o znaczenie i podstawy losowości. Niewiele z osób, dumnie nazywających się ,,data scientist” czy podobnie (w tym worku są też statystycy, machine learningowcy i ci co uważają, że to narzędzia rozwiązują problemy), zastanawia się nad własnościami wartości p, konsekwencjami aksjomatów Kołmogorowa i ich przystawaniem do rzeczywistości. Nie jest źle, jeżeli złożoność modelu bierze się z naszej (nie)wiedzy o rzeczywistości, ale gorzej jeżeli jest zasłoną dymną.

W analizie danych brakuje odpowiednika Bertranda Russella (dopiero niedawno przeczytałem Logikomiks, o którym pewnie też niedługo napiszę, ale już teraz polecam), który pomógłby opanować chaos w podejściu do analiz. Wielu badaczy zachłyśniętych regularyzacją, randomizacją, boostingiem zapomina o tym, że najczęściej dane nie pochodzą z symulacji i że używanie metody X tylko dlatego, że kolega ją lubi lub myśli, że ją rozumie, może nie być wystarczającym uzasadnieniem. Czy żyjemy na rosnącej bańce pompowanej przez szarlatanów? Z drugiej strony, cyrulicy z czasem przekształcili się w chirurgów.

Końcówka słaba. Aby nie było zbyt słodko, dodam że nie wszystko w książce Taleba mi się podoba. Wręcz wiele rzeczy mi się nie podoba. Autor niepotrzebnie, moim zdaniem, wplata w książkę wątki dotyczące etyki czy swojego światopoglądu. Nie chodzi nawet o to czy się z autorem zgadzam czy nie, ale o to, że książka przez to traci na precyzji. Są kontrowersyjne poglądy (np. że silna chemioterapia w przypadku niektórych nowotworów czyni więcej zła niż dobrego i nie wszystko co nie jest bardzo groźne warto leczyć), które moim zdaniem powinny albo iść w parze z konkretnymi dowodami albo się nie pojawiać. A nie żerować w sferze uogólnień i opinii. Miejscowe braki dowodów są spójne z tokiem rozumowania autora, a mianowicie, stwierdzeniem, że to twórcy terapii powinni dowodzić, że jest ona korzystna biorąc pod uwagę wszelkie, też długoterminowe, wyniki. Autor przyjmuje, że wszelkie interwencje są domyślnie niekorzystne o ile nie udowodni się, że jest inaczej.

Zdaniem Taleba czytamy książki, które są choć w części zgodne z naszymi poglądami. Co w książce Tabela spodobało mi się na tyle, że przeczytałem całość? Prawdopodobnie pochwała różnorodności, dzięki której złożone systemy mogą osiągnąć tytułową antykruchość.


7 days to go for submissions in the DataVis contest at useR!2014 (see contest webpage).
Note that the contest is open for all R users, not only conference participants.
Submit your solution soon!

PISA dataset allows to challenge some ,,common opinions”, like are boys or girls better in math / reading. But, how to compare differences between genders? Averages are not fancy enough ;-) Let’s use weighted quantiles calculated with function wtd.quantile() from the Hmisc package.

Below we present quantile-quantile plots for results in math and reading. Each point represents a single centile. X coordinate stands for centiles of male scores while Y coordinate correspond to female scores respectively. Black line is the diagonal, points on this line correspond to equal centiles in both distributions.
Points below black line correspond to centile for which boys are doing better than girls. Points above black line correspond to centiles for which girls are doing better. For reading the story is simple, girls are doing better for all centiles, whole distribution is shifted. But for math the story is different for different countries.

[UK - distribution of math scores for boys is shifted in comparison to females]

[Finland - distribution of math scores for boys is wider, weak boys are weaker than girls but strong one are stronger than corresponding girl's centile]

[USA - somewhere between Finland and UK]

What is the story for your country?

And the R code.

library(Hmisc)
library(ggplot2)
library(reshape2)
 
# read students data from PISA 2012
# directly from URL
con <- url("http://beta.icm.edu.pl/PISAcontest/data/student2012.rda")
load(con)
 
# plot quantiles for a country
plotCountry <- function(cnt) {
  cutoffs <- seq(0,1,0.01)
  selected <- student2012[student2012$CNT == cnt, ]
  getQuants <- function(group) {
    selectedG <- selected[group, ]
    wtd.quantile(selectedG$PV1MATH, weights=selectedG$W_FSTUWT, probs=cutoffs)
  }
  ecdf1 <- getQuants(selected$ST04Q01 == "Male")
  ecdf2 <- getQuants(selected$ST04Q01 == "Female")
  df1 <- data.frame(cutoffs, Male = ecdf1, Female = ecdf2, subject="MATH")
  getQuants <- function(group) {
    selectedG <- selected[group, ]
    wtd.quantile(selectedG$PV1READ, weights=selectedG$W_FSTUWT, probs=cutoffs)
  }
  ecdf1 <- getQuants(selected$ST04Q01 == "Male")
  ecdf2 <- getQuants(selected$ST04Q01 == "Female")
  df2 <- data.frame(cutoffs, Male = ecdf1, Female = ecdf2, subject="READ")
  df <- rbind(df1, df2)
  ggplot(df, aes(x = Male, y = Female, col = subject, shape = subject)) + 
    geom_point() +
    xlim(350,650) + ylim(350,650) + 
    geom_abline(intercept=0, slope=1) + ggtitle(cnt)
}  
 
# plot results for selected countries  
for (cnt in c("Canada", "United Kingdom","United States of America", "Finland"))
  ggsave(plotCountry(cnt), filename=paste0("Quant", cnt, ".png"), width=600/72, height=600/72)
top