Parsowanie stron HTML, meta-analiza, rak jelita i oczywiście obrazek

Dostałem dzisiaj pytanie od Macieja B. o kod użyty do wyciągania danych z portalu otomoto.pl.
Jak będę miał chwilę to ten kod wygładzę i opiszę na blogu, ale przy okazji dziś wpadłem na ciekawą funkcję służącą do parsowania danych, więc się nią podzielę.

Chodzi o funkcję readHTMLTable() z pakietu XML. Pozwala ona na wyciągnięcie danych z pliku HTML i wczytanie ich automatycznie do R.
Cool!
Jako przykład wykorzystamy zbiór danych o zachorowalności na nowotwór jelit w Wielkiej Brytanii, więcej o tym zbiorze danych i jego analizie przeczytać można na stronie http://blog.ouseful.info/2011/10/31/power-tools-for-aspiring-data-journalists-r/.

Poniższy fragment kodu wczytuje dane bezpośrednio ze strony HTML, dodaje nazwy kolumn i zmienia typy na liczbowe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
library(XML)
#
# funkcja readHTMLTable wyciaga tabele z danymi z pliku HTML
cancerdata <- readHTMLTable('http://www.guardian.co.uk/commentisfree/2011/oct/28/bad-science-diy-data-analysis', which=1)
colnames(cancerdata) <- c('Area','Rate','Population','Number')
for (i in 2:4) cancerdata[,i] <- as.numeric(as.character(cancerdata[,i]))
 
> # zobaczmy podsumwoanie wczytanych danych
> summary(cancerdata)
            Area          Rate         Population          Number      
 Aberdeen     :  1   Min.   : 9.16   Min.   :  31332   Min.   :  6.00  
 Aberdeenshire:  1   1st Qu.:15.22   1st Qu.: 140110   1st Qu.: 24.00  
 Adur         :  1   Median :17.44   Median : 189202   Median : 32.00  
 Allerdale    :  1   Mean   :17.64   Mean   : 224741   Mean   : 39.61  
 Amber Valley :  1   3rd Qu.:19.89   3rd Qu.: 267794   3rd Qu.: 45.00  
 Angus        :  1   Max.   :31.09   Max.   :1268959   Max.   :251.00  
 (Other)      :373

Skoro już ten zbiór danych wczytaliśmy to może jeszcze słowo komentarza skąd meta-analiza w nazwie tego wpisu. Zacznijmy od przedstawienia częstość zachorowań na nowotwór jelit na 100 tys mieszkańców a liczbę osób zamieszkałych na obszarze w którym ta częstość jest liczona.

1
2
3
4
5
6
7
8
library(lattice)
#
# wykres czestosci zachorowan od rozmiaru populacji
ktoreZNazwy <- with(cancerdata, Population^0.25 * Rate > 560 | Rate >= 27)
xyplot(Rate~Population, data = cancerdata, pch=19, col="red", panel=function(...) {
	panel.xyplot(...)
	with(cancerdata, ltext(Population[ktoreZNazwy], Rate[ktoreZNazwy], Area[ktoreZNazwy], cex=0.8, adj=c(0,-0.5)))
})

Dla małych miejscowości ocena częstości zachorowań obarczona jest większą przypadkowością, jeżeli mamy miasto o 100 mieszkańcach i jeden zachoruje to unormowana częstość skacze do 1000 na 100 tys. nawet jeżeli nie jest to obszar szczególnie narażony na podwyższone ryzyko. Dla zaludnionych obszarów takie losowe fluktuacje mają mały wpływ. Zmierza to w kierunku meta-analizy w której na podstawie pomiarów z wielu obszarów ocenilibyśmy oczekiwaną zmienność dla obszaru o zadanym zaludnieniu i porównywali ją z obserwowaną wartością, tutaj zachorowalności, na danym obszarze.

Na powyższym wykresie widać, że patrząc na częstość zachorowań Glasgow ma podobną zachorowalność jak Orkney Islands, ale jeżeli dodatkowo uwzględni się liczbę osób zamieszkałych na obu obszarach to Orkney Islands ma zachorowalność mieszczącą się w granicach losowych fluktuacji, a dla Glasgow zachorowalność ta jest znacząco powyżej oczekiwanej na bazie pomiarów z całego kraju. Ciekawe prawda. Kiedyś o meta-analizie napiszę więcej, bo warto. Co ciekawe o wykresie tunelowym (funnel-plot) bez skrępowania piszą w Wielkiej Brytanii takie gazety jak Guardian (http://www.guardian.co.uk/commentisfree/2011/oct/28/bad-science-diy-data-analysis). Jak widać nawet duże dzienniki mogą serwować rzetelne informacje a nie tylko plotki o tym co nowego u celebrytów.