Skip to content

1.5.8 Agregowanie danych

zozlak edited this page Oct 25, 2016 · 10 revisions

Niektórych analiz nie da się wykonać poprzez proste skorzystanie z funkcji wymienionych w rozdziale 1.5.2.

W szczególności może to dotyczyć przygotowania danych do prezentacji na wykresach (np. liowym albo rozrzutu) lub w tabelach o nieznanej z góry liczbie wierszy.

W takim wypadku niezbędna może okazać się samodzielna agregacja danych.

Przebiega ona zawsze w kilku krokach:

  • Utworzenie tablicy (w nomenklaturze R ramki danych) ze źródłowymi zmiennymi za pomocą funkcji data_table().
  • Zdefiniowanie zmiennych wyznaczających grupy za pomocą funkcji group_by().
  • Obliczenia agregatów dla grup za pomocą funkcji summarize() .

Najłatwiej zapoznać się z tym procesem na przykładzie.

Przykłady

Załóżmy, że dysponujemy zbiorem danych postaci:

Student Przedm Ocena
1 wstęp do socjologii 4
1 statystyka 2
2 statystyka 3
... ... ...

Nie znamy jednak z góry listy przedmiotów - nasz szablon raportu powinien dopasować się do listy przedmiotów, którą zastanie w zbiorze danych.

Tabela o nieznanej liczbie wierszy

Chcielibyśmy przedstawić średnie wyniki z poszczególnych przedmiotów w tabeli.

Ponieważ nie znamy z góry listy przedmiotów, nie możemy utworzyć szablonu tabeli, który będzie pasował do każdych danych.

Musimy skorzystać z funkcji TAB() (patrz rozdział 1.5.4.3), której przekażemy tablicę (ramkę danych) zagregowanych wartości do wyświetlenia.

Tak więc musimy najpierw wyliczyć zagregowane wartości.

Odnosząc się do przedstawionego na początku rozdziału schematu potrzebujemy:

  • Zdefiniować tablicę (ramkę danych) umieszczając w niej zmienne Przedm oraz Ocena.
    Nazwy, jakie nadajemy zmiennym w tworzonej ramce danych są dowolne, należy jedynie pamiętać, że:

    • w kolejnych krokach używać będziemy właśnie tych nowo nadanych nazw;
      w szczególności później wykorzystane funkcje (np. TAB() czy funkcje rysujące wykresy) mogą na ich podstawie nadawać nagłówki kolumn w tabeli czy etykiety serii danych na wykresie (z tego powodu przezywamy zmienną Przedm na Przedmiot);
    • w szczególności nadawane nazwy mogą być takie same, jak nazwy zmiennych źródłowych (jak tutaj w wypadku zmiennej Ocena)
    daneDoAgregacji = data_frame(
      Przedmiot = Przedm,
      Ocena  = Ocena
    )
    
  • Wskazać, że chcemy dokonać pogrupowania według zmiennej Przedmiot (która teraz nazywa się już Przedmiot):

    daneDoAgregacji = group_by(daneDoAgregacji, Przedmiot)
    
  • Policzyć zagregowane wartości za pomocą funkcji summarize() oraz funkcji obliczających statystki z pakietu MLAK (patrz rozdział 1.5.2):

    daneZagregowane = summarize(daneDoAgregacji, 'średnia ocena' = E(Ocena))
    

Mając obliczone agregaty, możemy je wyświetlić funkcją TAB(): TAB(daneZagregowane)

Cały kod w postaci wstawki w szablonie raportu wyglądałby następująco:

```{r}
daneDoAgregacji = data_frame(
    Przedmiot = Przedm,
    Ocena  = Ocena
)
daneDoAgregacji = group_by(daneDoAgregacji, Przedmiot)
daneZagregowane = summarize(daneDoAgregacji, 'Średnia ocena' = E(Ocena))
TAB(daneZagregowane)
```

Wykres słupkowy

Załóżmy, że zamiast tabeli z poprzedniego przykładu chcielibyśmy wyświetlić w raporcie wykres słupkowy.

W takim wypadku musimy przekształcić uzyskaną tablicę (ramkę danych) zagregowanych na wektor, którego wartościami będzie kolumna Średnia ocena a etykietami kolumna Przedmiot.

Możemy to uzyskać za pomocą funkcji setNames(wartości, etykiety):
daneDoWykresu = setNames(daneZagregowane$'Średnia ocena')

Cała wstawka w szablonie raportu, łącznie z narysowaniem wykresu, wyglądałaby następująco:

```{r, fig.width=3}
daneDoAgregacji = data_frame(
    Przedmiot = Przedm,
    Ocena  = Ocena
)
daneDoAgregacji = group_by(daneDoAgregacji, Przedmiot)
daneZagregowane = summarize(daneDoAgregacji, 'Średnia ocena' = E(Ocena))
daneDoWykresu = setNames(daneZagregowane$'Średnia ocena')
wykresSlupkowy(daneDoWykresu)
```

Sortowanie

Wróćmy do pierwszego przykładu (tabeli o nieznanej z góry liczbie wierszy).

Załóżmy, że zależy nam na tym, aby dane wyświetlone w raporcie były posortowane wedle wybranej kolumny, np. średniej oceny.

W tym celu wykorzystać można funkcję arrange(), którą wywołujemy na już obliczonych danych zagregowanych:
danePosortowane = arrange_(daneZagregowane, 'Średnia ocena')

Jeśli chcielibyśmy użyć do sortowania kilku kolumn, to wymieniamy ich nazwy po przecinku, np.:
danePosortowane = arrange_(daneZagregowane, 'Średnia ocena', 'Przedmiot').

Kompletny szablon raportu wyglądałaby następująco:

---
title: "Przykłady agregacji"
output: pdf_document
---
```{r, echo = FALSE, message = FALSE, warning = FALSE}
library(MLAK)
wczytajOdbiorce('odbiorcy.csv', 'dane.csv')
```
```{r}
daneDoAgregacji = data_frame(
    Przedmiot = Przedm,
    Ocena  = Ocena
)
daneDoAgregacji = group_by(daneDoAgregacji, Przedmiot)
daneZagregowane = summarize(daneDoAgregacji, 'Średnia ocena' = E(Ocena))
danePosortowane = arrange(daneZagregowane, 'Średnia ocena')
TAB(danePosortowane)
```

Złączanie kilku zbiorów danych

Czasami może się zdarzyć, że będziemy chcieli zagregować ze sobą zmienne o różnych poziomach agregacji i dopiero po ich połączeniu możliwe będzie obliczenie interesujących nas agregatów (patrz np. rozdział 1.5.7).

Jeśli zdarzy się taka sytuacja, złączenie przebiega w następującym schemacie:

  • Tworzymy oddzielne tablice (w nomenklaturze R ramki danych), z których każda zawieraja zmienne z jednego poziomu agregacji.
    • Odbywa to się tak samo, jak w wypadku agregacji - za pomocą funkcji data_frame(). Jedyna różnica polega na tym, że tym razem tworzymy dwie ramki danych, a nie jedną.
    • Tworzone ramki danych muszą zawierać co najmniej jedną zmienną o tej samej nazwie, po której odbędzie się złączenie.
  • Łączymy je ze sobą za pomocą jednej z funkcji (przykładowe wyniki złączeń można znaleźć tutaj):
    • inner_join(ramkaDanych1, ramkaDanych2) - w wynikowy zbiorze znajdą się tylko obserwacje, które występowały zarówno w ramkaDanych1, jak i ramkaDanych2,
    • left_join(ramkaDanych1, ramkaDanych2) - w wynikowym zbiorze znajdą się wszystkie obserwacje z ramkaDanych1 oraz wszystkie pasujące do nich obserwacje z ramkaDanych2,
    • full_join(ramkaDanych1, ramkaDanych2) - w wynikowym zbiorze znajdą się wszystkie obserwacje z obydwu ramek danych.

Przykład

Załóżmy, że dysponujemy dwoma zbiorami o różnych poziomach agregacji - pierwszym opisującym absolwenta na kierunku studiów i drugim opisującym absolwenta na kierunku studiów w danym miesiącu kalendarzowym:

ID_ZDAU DATA_ZAK DOSW_ES ...inne zmienne...
1 2015-10 1 ...pozostałe wartości...
2 2015-11 3 ...pozostałe wartości...
... ... ... ...

ID_ZDAU_M | OKRES_M | STUD_M | STUDPROG_M | BILOD_M | ...inne zmienne... ----------|---------|--------|------------|---------|--------|-------------------- 1 | 2015-10 | 1 | 1 | 0.62 | ...pozostałe wartości... 1 | 2015-11 | 0 | 0 | 0.80 | ...pozostałe wartości... ...|...| ...

Chcemy obliczyć średnią wartość zmiennej BILOD_M w grupach wyznaczanych przez zmienną DOSW_ES.

Złączenie zbiorów jest możliwe na podstawie wartości zmiennej ID_ZDAU w pierwszym zbiorze i ID_ZDAU_M w drugim zbiorze.

Zanim przystąpimy do agregacji, musimy złączyć ze sobą obydwa zbiory danych. W tym celu:

  • Tworzymy ramki danych zawierające potrzebne zmienne z obydwu zbiorów danych. Pamiętamy o tym, że obydwie ramki danych muszą zawierać kolumnę o takiej samej nazwie, która umożliwi złączenie:

    zbior1 = data_frame(
      ID_ZDAU = ID_ZDAU,
      DOSW_ES = DOSW_ES
    )
    zbior2 = data_frame(
      ID_ZDAU = ID_ZDAU_M,
      BILOD_M = BILOD_M
    )
    
  • Złączamy dane ze sobą. Tu wykorzystamy złączenie inner_join():
    daneZlaczone = inner_join(zbior1, zbior2)

  • Teraz możemy już dokonać agregacji, jak to zostało omówione w pierwszej części rozdziału.

Pełen szablon raportu dokonujący złączenia zbiorów, agregacji, a na końcu wstawiającej wynik obliczeń do raportu w postaci tabeli wyglądałby następująco:

---
title: "Przykłady agregacji"
output: pdf_document
---
```{r, echo = FALSE, message = FALSE, warning = FALSE}
library(MLAK)
wczytajOdbiorce('odbiorcy.csv', 'dane.csv')
```
```{r}
zbior1 = data_frame(
    ID_ZDAU = ID_ZDAU,
    DOSW_ES = DOSW_ES
)
zbior2 = data_frame(
    ID_ZDAU = ID_ZDAU_M,
    BILOD_M = BILOD_M
)
daneZlaczone = inner_join(zbior1, zbior2)
daneDoAgregacji = group_by(daneZlaczone, DOSW_ES)
daneZagregowane = summarize(daneDoAgregacji, BILOD = E(BILOD))
TAB(daneZagregowane)
```