Pakiet plyr, czyli co nowego w ,,Przewodniku po pakiecie R” wydanie trzecie.

Przygotowuję trzecie wydanie ,,Przewodnika po pakiecie R”. Zmiany w stosunku do wydania drugiego są spore, kilka rzeczy zostało usuniętych, kilka dodanych.

Jedna z dodanych rzeczy to bardziej rozbudowany rozdział o funkcjach z rodziny apply i plyr. Poniżej przeklejam część nowego wydania ,,Przewodnika …” poświęconą pakietowi plyr. Przepraszam też za ewentualne usterki związane z konwersją LaTeXa do HTMLa.


Fragment książki ,,Przewodnik po pakiecie R”, Przemysław Biecek, wydawnictwo GiS, wydanie 3.

W podejściu z użyciem pary plyr+reshape2, pakiet reshape2 służy to zmiany struktury zbioru danych, a pakiet plyr służy do automatyzacji obliczeń, na odpowiednio przygotowanej strukturze danych. Poniżej przedstawiam krótkie wprowadzenie. Osobom zainteresowanym poznaniem dalszych szczegółów polecam prace http://www.jstatsoft.org/v21/i12/paperhttp://www.jstatsoft.org/v40/i01/paper.

Zacznijmy od przedstawienia pakietu reshape2. W tym pakiecie godne uwagi są trzy funkcje: reshape2::melt(), reshape2::acast()reshape2::dcast(). Funkcja melt() ,,roztapia” dane z postaci tabelarycznej (również dla tabel wielowymiarowych) do tzw. postaci wąskiej (nazywanej też postacią rzadką lub postacią wiersz-kolumna-wartość (RCV od ang. row column value). Funkcja acast() pozwala na przekształcenie danych z postaci wąskiej na postać tabeli krzyżowej (przestawnej), gdzie wartościami pól tej tabeli są wartości zadanej funkcji wyznaczonej na podzbiorze danych.

Przedstawmy obie funkcje na przykładzie. Wykorzystamy pakiet SmarterPoland do pobrania z internetowych baz Eurostatu danych o częstości wypadków drogowych w różnych latach, różnych krajach. Takie dane znajdują się w tabeli tsdtr420 w bazie Eurostatu.

Poniżej wykorzystujemy funkcję SmarterPoland::getEurostatRCV() do pobrania danych z tabeli tsdtr420.

Kilka pierwszych wierszy z pobranych danych. W kolejnych kolumnach są: nazwa opisywanego współczynnika, identyfikator kraju, roku oraz liczba ofiar wypadków.

Podsumowanie danych z częstościami wystąpień zmiennych czynnikowych.

Zmienna wypadkiWaska jest już w postaci roztopionej. Pierwsze trzy kolumny opisują trzy różne wymiary. Tutaj są to: rodzaj statystyki (liczba ofiar i liczba ofiar przeliczona na milion mieszkańców), identyfikator kraju, rok, którego dotyczy statystyka. Czwarta kolumna określa wartość zadanej statystyki dla wybranego kraju w wybranym roku. W tym przypadku postać wąska opisuje trzy wymiary zmiennych, ale można rozważać zarówno dane o większej jak i o mniejszej liczbie wymiarów.

Wykorzystajmy teraz funkcję dcast() aby przekształcić te dane do postaci tabelarycznej z krajami w wierszach i latami w kolumnach. Przyjmijmy, że interesuje nas wyłącznie statystyka KIL_MIO_POP (,,ofiary na milion mieszkańców”).

Pierwszym argumentem jest ramka danych w postaci roztopionej. Drugim jest formuła opisująca, które wymiary chcemy by były w wierszach (lewa strona formuły) a które w kolumnach (prawa strona formuły). Argument subset określa, które wiersze z wejściowego zbioru danych brać pod uwagę. Trzeci argument wskazuje funkcję, która będzie zastosowana do wszystkich wierszy ramki wypadkiWaska wskazujących na ten sam rok i kraj. W rozważanym przypadku rok i kraj wyznaczają dokładnie jeden wiersz, więc użycie funkcji mean() może wydawać się nadmiarowe, za każdym razem jest to bowiem liczenie średniej z jednej wartości.

Dla ćwiczeń roztopimy teraz zbiór danych wypadkiSzeroka, sprowadzając go z powrotem do postaci wąskiej z użyciem funkcji melt().

Teraz omówmy wybrane, przydatne funkcje z pakietu plyr. Tabela [plyrTabela] przedstawia nazwy wszystkich interesujących funkcji. Jednak nie będziemy ich wszystkich omawiać, ponieważ ich sposób działania jest bardzo podobny i wystarczy omówić kilka wybranych przykładów by wiedzieć jak korzystać z pozostałych.

wejście \ wyjście macierz ramka danych lista nic
macierz aaply() adply() alply() a\_ply()
ramka danych daply() ddply() dlply() d\_ply()
lista laply() ldply() llply() l\_ply()
n powtórzeń raply() rdply() rlply() r\_ply()
zbiór argumentów maply() mdply() mlply() m\_ply()

Tabela: Wybrane funkcje z~pakietu \texttt{plyr} do przetwarzania potokowego. W~kolumnach zaznaczono jakiego typu jest wynik funkcji, czy jest to macierz, ramka danych, lista czy też funkcja nie zwraca wartości. W~wierszach zaznaczono co jest argumentem wejściowym, czy jest to macierz danych, ramka danych, lista zbiorów~danych.

Schemat działania funkcji z tego pakietu jest określany ,,dziel/przekształć/łącz” (ang. split/apply/combine). Przetwarzanie potokowe oznacza, że ta sama funkcja jest stosowana do różnych podzbiorów wejściowego zbioru danych. W pierwszym kroku ten zbiór danych jest dzielony na podzbioru najczęściej z uwagi na wybrane zmienne grupujące (etap ang. split), następnie do każdego wydzielonego podzbioru stosowana jest zadana funkcja (etap ang. apply) w ostatnim kroku otrzymane wyniki są łączone (etap ang. combine).

Konwencja nazywania funkcji jest ujednolicona, pierwsza litera odpowiada formatowi argumentów wejściowych, druga formatowi wyniku następnie występuje sufiks ply(). Litera a oznacza macierz (array), d ramkę danych, l listę, _ nic (funkcji, które nie zwracają wyniku używa się dla ich ,,efektów ubocznych”, np rysowania wykresów). Prefiks r oznacza powtórzenie pewnej operacji n-krotnie na całym zbierze danych, a prefiks m oznacza powtórzenie tej samej funkcji dla zadanego zbioru różnych argumentów wejściowych.

W przypadku pierwszy trzech wierszy tabeli [plyrTabela] funkcje prezentowane różnią się typem wejścia i wyjścia. Mechanizm działania jest podobny. Poniżej przedstawimy tylko funkcje ddply()llply(). Argumenty tych funkcji są następujące: zbiór danych wejściowych, wskazanie zmiennych grupujących, wskazanie funkcji do zastosowania na każdym podzbiorze, dodatkowe argumenty dla tej funkcji. Zmienne grupujące można wskazać na różne sposoby: podając wektor nazw, formułę lub używając funkcji .(), która nic nie robi ale umożliwia podanie jako argumentów nazw kolumn ze zbioru danych.

W przykładzie poniżej zbiór danych wypadkiRoztopiona podzielimy ze względu na podzbiory określone zmienną geo (czyli podzbiory danych to dane dla różnych krajów). Następnie na każdym podzbiorze wykonamy funkcję lm(), która dla każdego podzbioru wyznaczy współczynniki regresji liniowej – zależności liczby wypadków od roku. Zarówno wejściem jak i wyjściem funkcji jest ramka danych.

Często używając funkcji z rodziny **ply() wykorzystuje się funkcje summarize()transform(). Obie pozwalają na uniknięcie potrzeby tworzenia funkcji anonimowych. Funkcja summarize() jako wynik zwraca wskazane podsumowania każdego podzbioru danych (w poniższym przypadku będą to współczynniki modelu liniowego i średnia liczba wypadków). Funkcja transform() jako wynik zwraca przekształcony zbiór danych z dodanymi nowymi kolumnami.

Poniżej zaprezentujemy przykład użycia funkcji llply(). Oczekuje ona jako argumentu wejściowego listy. Aby taką listę otrzymać posłużymy się funkcją split().

Użycie funkcji llply() jest identyczne z funkcją ddply(), z tą różnicą, że wejście i wyjście jest teraz listą.

Ciekawą funkcją, którą omówimy poniżej jest r*ply(). Powtarza ona wykonanie pewnej operacji zadaną liczbę razy, przez co działa podobnie co funkcja replicate() ale mamy większą kontrolę nad typem wyniku.

9 myśli na temat “Pakiet plyr, czyli co nowego w ,,Przewodniku po pakiecie R” wydanie trzecie.”

  1. Fajnie, a kiedy będzie na rynku?
    Można by też uwzględnić pakiet dplyr (https://github.com/hadley/dplyr):
    “Currently, it’s not a good idea to have both dplyr and plyr loaded. This is just a short-term problem: in the long-term, I’ll move the matching functions from plyr into dplyr, and add a dplyr dependency to plyr.”

    1. Dzięki, pomysł przyszłościowy. Na dzień dzisiejszy pakiet dplyr jeszcze nie jest dopracowany (może mu się przydarzyć to co pakietowi reshape). Ale jak będzie dostępny w stabilnej wersji to go opiszemy. Na useR HW przedstawiał zyski w czasie przetwarzania i faktycznie dplyr jest znacznie szybszy niż plyr, choć nieznacznie wolniejszy od data.table.

      Dla dużych danych bardziej przyszłościowe jednak wydaje mi się bliższa integracja z bazą danych czy hadoopem. Na razie RAM jest zbyt dużym ograniczeniem.

    2. A co do dostępności, to mam nadzieję, że będzie do kupienia od przełomu sierpnia/września. Kończę właśnie skład. Jeszcze czyszczenie z literówek i gotowe.

  2. Sporo drobiazgów, ale z dużych rzeczy to opis pakietów knitr, shiny i slidify.

    W czwartek będzie wpis o shiny [ta biblioteka jest fantastyczna], w przyszły wtorek o zmianach w typografi [tych jest dużo] a w przyszły czwartek przedmowa do trzeciego wydania.

  3. Jakiś czas temu byłem dużym zwolennikiem wersji mobilnych, ale ograniczała mnie technologia.
    Teraz mam wrażenie, że to dobra platforma dla książek liniowych, które można czytać akapit po akapicie, w których nie jest zbyt wielu tabel czy rysunków, skorowidz też nie jest zbyt potrzebny. [jeżeli się mylę to popraw mnie].
    ,,Przewodnik” ma za to wiele komentarzy na maginesie, odsyłaczy do innych rozdziałów, wtrąceń, uwag. Przerobienie go na taką liniową postać nie byłoby zbyt proste.
    Krótka odpowiedź na Twoje pytanie jest więc: może w przyszłości, ale nieprędko.

  4. Trudne pytanie. W lipcu myślałem, że będzie to możliwe w sierpniu. Dzisiaj myślę, że będzie to możliwe w grudniu. Napiszę na blogu gdy trzecie wydanie trafi do księgarń.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">