4  Przetwarzanie danych - dplyr

4.1 Pakiety

4.1.1 Pakiet dplyr

Pakiet dplyr wykorzystuje się do podstawowych operacji przetwarzania danych z wykrzystaniem obiektów typu data.frame. Podstawowe funkcje pakietu to:

  • select() - tworzenie podzbioru danych poprzez wybór zmiennych na podstawie ich nazw,
  • filter() - tworzenie podzbioru danych poprzez wybór wierszy na podstawie określonego warunku,
  • arrange() - sortowanie danych,
  • mutate() - tworzenie nowych zmiennych na podstawie określenia warunku,
  • summarize() - podsumowanie danych, np. poprzez obliczenie statystyk podstawowych.

Pakiet dplyr dostarcza także funkcji:

  • do grupowania danych: group_by() - pozwala na wykonanie operacji w podziale na grupy.
  • do łączenia dwóch lub więcej obiektów (data.frame): join(), left_join(), right_join()

Pakiet dplyr pozwala także na wykorzystanie operatora łączącego funkcje %>%

Więcej informacji:

4.1.2 Pakiet tidyr

Dane wykorzysywane w analizach muszą być przechowywane w tzw. uporządkowany sposób (ang. tidy data). Uporządkowane dane to dane, w których:

  • każda zmienna przechowywana jest w osobnej kolumnie.
  • każda obserwacja jest zapisana w osobnym wierszu w tabeli danych
  • każda wartość przechowywana jest w osobnej komórce (tzn. każda komórka przechowuje tylko jedną wartość).

Pakiet tidyr() zawiera zestaw funkcji, które ułatwiają tworzenie uporządkowanych danych. Uporządkowane dane mogą być przechowywane w dwóch układach: układzie długim i układzie szerokim (więcej informacji w podrozdziale Sekcja 4.3)

Więcej informacji:

4.2 Przetwarzanie danych z pakietem dplyr

4.2.1 Funkcja select()

  • Wybór kolumn country, year oraz pop.
sel1 <- select(gapminder, country, year, pop)
head(sel1)
# A tibble: 6 × 3
  country      year      pop
  <fct>       <int>    <int>
1 Afghanistan  1952  8425333
2 Afghanistan  1957  9240934
3 Afghanistan  1962 10267083
4 Afghanistan  1967 11537966
5 Afghanistan  1972 13079460
6 Afghanistan  1977 14880372

Ze zbioru danych gapminder proszę wybrać dane dla zmiennych country, year oraz lifeExp.

  • Wybór wszystkich kolumn z wyjątkiem kolumny kontynent
sel2 <- select(gapminder, -continent)
head(sel2)
# A tibble: 6 × 5
  country      year lifeExp      pop gdpPercap
  <fct>       <int>   <dbl>    <int>     <dbl>
1 Afghanistan  1952    28.8  8425333      779.
2 Afghanistan  1957    30.3  9240934      821.
3 Afghanistan  1962    32.0 10267083      853.
4 Afghanistan  1967    34.0 11537966      836.
5 Afghanistan  1972    36.1 13079460      740.
6 Afghanistan  1977    38.4 14880372      786.

Ze zbioru danych gapminder proszę wybrać wszystkie kolumny z wyjątkiem continent oraz gdpPercap.

4.2.2 Funkcja filter()

Funkcja filter() służy do tworzenia podzbiorów danych poprzez wybór obserwacji spełniających określone warunki. Warunki są określane za pomocą operatorów logicznych (!=, ==, >, <, >=, <=, |, &).

  • Wybór danych dla roku 2007.
filt1 <- filter(gapminder, year == 2007)
head(filt1)
# A tibble: 6 × 6
  country     continent  year lifeExp      pop gdpPercap
  <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
1 Afghanistan Asia       2007    43.8 31889923      975.
2 Albania     Europe     2007    76.4  3600523     5937.
3 Algeria     Africa     2007    72.3 33333216     6223.
4 Angola      Africa     2007    42.7 12420476     4797.
5 Argentina   Americas   2007    75.3 40301927    12779.
6 Australia   Oceania    2007    81.2 20434176    34435.

Wybierz dane dla kontynentu Europa.

W jaki inny sposób można wybrać dane dla roku 2007?

  • Wybór danych dla roku 2007, w których oczekiwana długość trwania życia przekracza 80 lat.
filt2 <- filter(gapminder, year == 2007 & lifeExp > 80)
filt2
# A tibble: 13 × 6
   country          continent  year lifeExp       pop gdpPercap
   <fct>            <fct>     <int>   <dbl>     <int>     <dbl>
 1 Australia        Oceania    2007    81.2  20434176    34435.
 2 Canada           Americas   2007    80.7  33390141    36319.
 3 France           Europe     2007    80.7  61083916    30470.
 4 Hong Kong, China Asia       2007    82.2   6980412    39725.
 5 Iceland          Europe     2007    81.8    301931    36181.
 6 Israel           Asia       2007    80.7   6426679    25523.
 7 Italy            Europe     2007    80.5  58147733    28570.
 8 Japan            Asia       2007    82.6 127467972    31656.
 9 New Zealand      Oceania    2007    80.2   4115771    25185.
10 Norway           Europe     2007    80.2   4627926    49357.
11 Spain            Europe     2007    80.9  40448191    28821.
12 Sweden           Europe     2007    80.9   9031088    33860.
13 Switzerland      Europe     2007    81.7   7554661    37506.

Wybór danych dla roku 2007, dla wszystkich kontynentów z wyjątkiem Azji, w których oczekiwana długość trwania życia przekracza 80 lat.

4.2.3 Funkcja mutate()

Funkcja mutate() służy do tworzenia nowych zmiennych na podstawie określonego wyrażenia

  • Dodaj kolumnę abbr_country zawierającą trzyliterowy kod państwa.
gap2 <- mutate(gapminder, abbr_country = toupper(substr(country, 1, 3)))
head(gap2)
# A tibble: 6 × 7
  country     continent  year lifeExp      pop gdpPercap abbr_country
  <fct>       <fct>     <int>   <dbl>    <int>     <dbl> <chr>       
1 Afghanistan Asia       1952    28.8  8425333      779. AFG         
2 Afghanistan Asia       1957    30.3  9240934      821. AFG         
3 Afghanistan Asia       1962    32.0 10267083      853. AFG         
4 Afghanistan Asia       1967    34.0 11537966      836. AFG         
5 Afghanistan Asia       1972    36.1 13079460      740. AFG         
6 Afghanistan Asia       1977    38.4 14880372      786. AFG         

Co w powyższym poleceniu robi funkcja substr() oraz toupper()?

Dodaj do zbioru danych kolumnę pop_mln zawierająca liczbę ludności w milionach.

4.2.4 Funkcja arrange()

Funkcja arrange() wykorzystywana jest do sortowania danych.

  • Sortowanie rosnące względem zmiennej lifeExp
arr1 <- arrange(gapminder, lifeExp)
head(arr1)
# A tibble: 6 × 6
  country      continent  year lifeExp     pop gdpPercap
  <fct>        <fct>     <int>   <dbl>   <int>     <dbl>
1 Rwanda       Africa     1992    23.6 7290203      737.
2 Afghanistan  Asia       1952    28.8 8425333      779.
3 Gambia       Africa     1952    30    284320      485.
4 Angola       Africa     1952    30.0 4232095     3521.
5 Sierra Leone Africa     1952    30.3 2143249      880.
6 Afghanistan  Asia       1957    30.3 9240934      821.
  • Sortowanie malejące względem zmiennej lifeExp
arr2 <- arrange(gapminder, desc(lifeExp))
head(arr2)
# A tibble: 6 × 6
  country          continent  year lifeExp       pop gdpPercap
  <fct>            <fct>     <int>   <dbl>     <int>     <dbl>
1 Japan            Asia       2007    82.6 127467972    31656.
2 Hong Kong, China Asia       2007    82.2   6980412    39725.
3 Japan            Asia       2002    82   127065841    28605.
4 Iceland          Europe     2007    81.8    301931    36181.
5 Switzerland      Europe     2007    81.7   7554661    37506.
6 Hong Kong, China Asia       2002    81.5   6762476    30209.

Posortuj dane malejąco względem zmiennej pop.

  • Sortowanie rosnące względem kontynentu (continent) oraz oczekiwanej długości trwania życia (lifeExp)
arr3 <- arrange(gapminder, continent, lifeExp)
head(arr3)
# A tibble: 6 × 6
  country      continent  year lifeExp     pop gdpPercap
  <fct>        <fct>     <int>   <dbl>   <int>     <dbl>
1 Rwanda       Africa     1992    23.6 7290203      737.
2 Gambia       Africa     1952    30    284320      485.
3 Angola       Africa     1952    30.0 4232095     3521.
4 Sierra Leone Africa     1952    30.3 2143249      880.
5 Mozambique   Africa     1952    31.3 6446316      469.
6 Sierra Leone Africa     1957    31.6 2295678     1004.

Posortuj malejąco względem nazwy państwa oraz rosnąco względem liczby ludności.

4.2.5 Funkcja rename()

Funkcja rename() służy do zmiany nazw kolumn. W funkcji rename() definiujemy nowa_nazwa = stara_nazwa.

  • Zmiana nazw kolumn na polskie nazwy.
gap2 <- rename(gapminder, panstwo = country, kontynent = continent, rok = year, dlugosc_zycia = lifeExp, ludnosc = pop, PKB = gdpPercap)
names(gap2)
[1] "panstwo"       "kontynent"     "rok"           "dlugosc_zycia"
[5] "ludnosc"       "PKB"          

Korzystając ze strony pomocy funkcji rename() sprawdź jak w zmienić nazwy kolumn w obiekcie gap2 na drukowane litery.

4.2.6 Funkcja summarize()

Funkcja summarize() służy do wykonywania podsumowań statystycznych. Tworzy kolumny z zadanymi statystykami.

  • Średnia oczekiwana długość trwania życia.
smr1 <- summarize(gapminder, 
          srednia = mean(lifeExp))
smr1
# A tibble: 1 × 1
  srednia
    <dbl>
1    59.5
  • Średnia, minimalna oraz maksymalna oczekiwana długość trwania życia.
smr2 <- summarize(gapminder, 
          srednia = mean(lifeExp),
          min = min(lifeExp),
          max = max(lifeExp))
smr2
# A tibble: 1 × 3
  srednia   min   max
    <dbl> <dbl> <dbl>
1    59.5  23.6  82.6

Oblicz średnią, odchylenie standardowe, minimum i maksimum dla zmiennej gdpPercap.

4.2.7 Grupowanie .by

  • argument .by; np. summarize(, .by) - grupowanie dokonywane tylko na potrzeby danej funkcji
grp1 = summarize(filt1 ,
                 srednia = mean(lifeExp), 
                 .by = continent)
grp1
# A tibble: 5 × 2
  continent srednia
  <fct>       <dbl>
1 Asia         70.7
2 Europe       77.6
3 Africa       54.8
4 Americas     73.6
5 Oceania      80.7

Oblicz minimalną i maksymalną długość trwania życia w 2007 roku w podziale na kontynenty.

4.2.8 Funkcja pull()

Funkcja pull() służy do wyciągania tylko jednej zmiennej

life_exp <- pull(gapminder, lifeExp)
head(life_exp)
[1] 28.801 30.332 31.997 34.020 36.088 38.438
continent <- pull(gapminder, continent)
head(continent)
[1] Asia Asia Asia Asia Asia Asia
Levels: Africa Americas Asia Europe Oceania

Wybierz ze zbioru danych kolumnę pop.

4.2.9 Operator łączący (%>%).

Używając pakietu dplyr można łączyć ze sobą funkcje używając operatora %>%

Przykład

Które kraje w roku 1952 miały liczbę ludności powyżej 100 milionów?

Aby odpowiedzieć na to pytanie możemy wykonać każdą operację osobno, i jej wynik zapisać w osobnym obiekcie. Operator łączący %>% pozwala natomiast na przekazanie wyniku działania jednej funkcji do drugiej, bez tworzenia osobnych obiektów.

f1 <- filter(gapminder, pop > 100000000 & year == 1952)
s1 <- select(f1, country, pop)
a1 <- arrange(s1, pop) # sortowanie danych wzgledem pop
a1
# A tibble: 3 × 2
  country             pop
  <fct>             <int>
1 United States 157553000
2 India         372000000
3 China         556263527
  • Wykorzystanie operatora łączącego %>%
df <- gapminder %>%  #wejsciowy zbior danych
  filter(pop > 100000000 & year == 1952) %>% # wybor krajow z pop > 100mln w roku 1952
  select(country, pop) %>% # wybor kolumn country, pop 
  arrange(pop) # sortowanie danych wzgledem pop

df
# A tibble: 3 × 2
  country             pop
  <fct>             <int>
1 United States 157553000
2 India         372000000
3 China         556263527

Które kraje w 2007 roku miały populację powyżej 100 milionów? Posortuj wynik od krajów z największą liczbą ludności do krajów z najmniejszą liczbą ludności.

4.2.10 Funkcja join()

x <- data.frame(country = c("Poland", "USA", "Germany"), pop = c(36.82, 333.3, 83.8))

y = data.frame(country = c("Poland", "USA", "Italy"), pop = c(36.82, 333.3, 58.94))
x
  country    pop
1  Poland  36.82
2     USA 333.30
3 Germany  83.80
y
  country    pop
1  Poland  36.82
2     USA 333.30
3   Italy  58.94
  • Funkcja inner_join(x, y) zwraca tylko obiekty występujące w obu tabelach
inner_df <- inner_join(x, y, by = 'country')
inner_df 
  country  pop.x  pop.y
1  Poland  36.82  36.82
2     USA 333.30 333.30
  • Funkcja left_join(x, y) zachowuje wszystkie obserwacje w x, niezależnie od tego, czy mają swój odpowiednik w tabeli y. Jest to najczęściej używane łączenie, ponieważ gwarantuje, że nie utracimy obserwacji z tabeli podstawowej (x).
left_df <- left_join(x, y, by = 'country')
left_df
  country  pop.x  pop.y
1  Poland  36.82  36.82
2     USA 333.30 333.30
3 Germany  83.80     NA
  • Funkcja right_join(x, y) zachowuje wszystkie obserwacje w y.
right_df <- right_join(x, y, by = 'country')
right_df
  country  pop.x  pop.y
1  Poland  36.82  36.82
2     USA 333.30 333.30
3   Italy     NA  58.94
  • Funkcja full_join(x, y) zwraca wszystkie obiekty z tabeli x oraz z tabeli y.
full_df <- full_join(x, y, by = 'country')
full_df
  country  pop.x  pop.y
1  Poland  36.82  36.82
2     USA 333.30 333.30
3 Germany  83.80     NA
4   Italy     NA  58.94

4.3 Układ danych

Dane w tabeli mogą być zapisywane w układzie długim lub szerokim.

Układ danych (po lewej) - szeroki; (po prawej) długi

Zmiana układu danych jest możliwa z użyciem funkcji z pakietu tidyr.

library(tidyr)
  • Układ długi

Dane gapminder są zapisane w układzie długim:

head(gapminder, 10)
# A tibble: 10 × 6
   country     continent  year lifeExp      pop gdpPercap
   <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
 1 Afghanistan Asia       1952    28.8  8425333      779.
 2 Afghanistan Asia       1957    30.3  9240934      821.
 3 Afghanistan Asia       1962    32.0 10267083      853.
 4 Afghanistan Asia       1967    34.0 11537966      836.
 5 Afghanistan Asia       1972    36.1 13079460      740.
 6 Afghanistan Asia       1977    38.4 14880372      786.
 7 Afghanistan Asia       1982    39.9 12881816      978.
 8 Afghanistan Asia       1987    40.8 13867957      852.
 9 Afghanistan Asia       1992    41.7 16317921      649.
10 Afghanistan Asia       1997    41.8 22227415      635.
  • Układ szeroki

Funkcja pivot_wider() przekształca dane z formatu długiego w szeroki. Obiekt gapminder_wide w każdej kolumnie przechowuje dane dla jednego roku, a w każdym wierszu dla kraju.

gapminder2 <- select(gapminder, -continent, 
                    -lifeExp, -gdpPercap)
gapminder_wide <- pivot_wider(gapminder2, 
                             names_from = year, 
                             values_from = pop)

head(gapminder_wide)
# A tibble: 6 × 13
  country  `1952` `1957` `1962` `1967` `1972` `1977` `1982` `1987` `1992` `1997`
  <fct>     <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>  <int>
1 Afghani… 8.43e6 9.24e6 1.03e7 1.15e7 1.31e7 1.49e7 1.29e7 1.39e7 1.63e7 2.22e7
2 Albania  1.28e6 1.48e6 1.73e6 1.98e6 2.26e6 2.51e6 2.78e6 3.08e6 3.33e6 3.43e6
3 Algeria  9.28e6 1.03e7 1.10e7 1.28e7 1.48e7 1.72e7 2.00e7 2.33e7 2.63e7 2.91e7
4 Angola   4.23e6 4.56e6 4.83e6 5.25e6 5.89e6 6.16e6 7.02e6 7.87e6 8.74e6 9.88e6
5 Argenti… 1.79e7 1.96e7 2.13e7 2.29e7 2.48e7 2.70e7 2.93e7 3.16e7 3.40e7 3.62e7
6 Austral… 8.69e6 9.71e6 1.08e7 1.19e7 1.32e7 1.41e7 1.52e7 1.63e7 1.75e7 1.86e7
# ℹ 2 more variables: `2002` <int>, `2007` <int>

Wybierz z danych kolumnę lifeExp oraz year i zamień dane na układ szeroki.

  • Układ szeroki -> Układ długi

Wybierz z danych kolumnę gdpPercap oraz year i zamień dane na układ szeroki. Następnie z układu szerokiego zamień dane na układ długi.