Wykład 6

Author

Jakub Wilk

Published

November 6, 2023

1 Wykład 6 - Tidyverse I dplyr

  • ggplot2 Wizualizacja danych
  • dplyr Przetwarzanie danych
  • tidyr Porządkowanie danych
  • readr Wczytywanie danych
  • purrr Programowanie funkcyjne
  • tibble Efektywniejsza odmiana ramki danych
  • stringr Zmienne znakowe (character)
  • forcats Zmienne jakościowe (factor)

1.1 tibble → nowy dataframe

mtcars <- as_tibble(mtcars)
print(mtcars, n = 5, width = Inf)
tribble(
  ~x, ~y,  ~z,
  "a", 2,  3.6,
  "b", 1,  8.5
)

2 dplyr

przeprowadza selekcję wierszy

dane |> filter(waga > 70)
dane |> filter(stanow %in% c("asystent", 
                             "adiunkt", 
                             "prof."))
dane |> filter(between(wzrost, 174, 185)) # pomiędzy
dane |> 
  filter(!(kraj == "PL"))
dane |> 
  filter(kraj == "USA" | "PL")  # zwraca błąd
dane |> 
  filter(kraj == "USA" | kraj == "PL") # porpawny kod

zmieniają kolejność wierszy (sortowanie)

dane |> arrange(desc(nazwisko, imie))
# na poczatku bierze nazwisko a potem imie

znajduje wiersze o unikalnych wartościach dane |> distinct(plec, kraj) dane |> distinct(kraj) -> wybiera unikalne kraje

2.1 Ćwiczenia z filter, arange i distinct

  • Przekształć zestaw danych auta na obiekt typu tibble.
  • Posortuj auta względem mocy silnika KM i pojemności skokowej Pojemnosc.skokowa.
  • Wybierz tylko auta marki Rolls-Royce i posortuj je po cenie.
  • Wyświetl tylko 5 najdroższych samochodów.
#zadanie 3.1.2
auta <-   as_tibble(auta2012) |>  
 arrange(KM, Pojemnosc.skokowa) |> 
  filter(Marka == "Rolls-Royce") |> 
  arrange(desc(Cena)) |>   
head(n = 5)

W jednym potoku dla każdego warunku znajdź wszystkie loty spełniające niżej wymienione warunki:

lot miał opóźnienie przybycia wynoszące dwie lub więcej godzin [arr_delay] Wyleciał latem (lipiec, sierpień i wrzesień) [month] Przybyłem z ponad dwugodzinnym opóźnieniem, ale nie wystartował z opóżnieniem [arr_delay, dep_delay]

fl |> 
  filter(arr_delay > 120) 

fl |> 
  filter(dest %in% c("IAH", "HOU"))
 
fl |> 
  filter(month == 7 | month == 9 | month == 9)
  
fl |> 
  filter(arr_delay > 120 & dep_delay <= 0) 

fl |> 
  filter(dep_delay >= 60 & dep_delay - arr_time > 30) 

# Zauważ, że nie stosuje nawiasów, oznacza to, że operacje arytmetyczne mają
# pierwszeństwo przed operatorami logicznymi. 

Sortuj flights, aby znaleźć loty z największym opóźnieniem z posród lotów które zgodnie z planem miały wystartować miedzy 5:00 a 8:00 rano.

# sortowanie 
fl |> 
  arrange(arr_delay |> desc()) 

# altrnatywnie selekcja
fl |> 
  slice_max(arr_delay, n = 5)

# sortowanie plus okienko czasu

fl |> 
  filter(between(hour, 5, 7) | hour == 8 & minute == 0) |> 
  arrange(arr_delay |> desc())

Które samoloty przebyły najdłuższy dystans? Który przebył najmniejszy dystans?

fl1 <- fl |> 
    slice_max(distance, n = 1) # wiele samolotów

fl |> 
  slice_max(distance, n = 1) |> 
  pull(tailnum) |> 
  unique() 

fl |> 
  slice_min(distance, n = 1, na_rm = T) # niestety nie posiada identyfikatora brak danych

# usuniemy braki danych o numerach samolotów i otrzymamy następujace wyniki

fl |> 
  filter(!is.na(tailnum)) |> 
  slice_min(distance, n = 1) |> 
  pull(tailnum) |> 
  unique()
dane |> 
  slice(
    seq(1, nrow(dane), 2)
    ) # co drugi
dane |> 
  slice(
    sample(1:nrow(dane), size = 5, replace = F)
    ) # 5 losowych
dane |> 
  slice_sample(n = 20, replace = T) # losuje okreśoną liczbę wierszy

dane |> 
  slice_min(waga, n = 3) # najniższe wartości zmiennjej waga

dane |> 
  slice_max(waga, n = 3) # najwyższe wartości zmiennej waga

dane |> slice_head() # pierwsz, n = definiuje ilość wierszy 

dane |> slice_tail() # ostatni, n = definiuje ilość wierszy 

2.2 Inne operacje

# unikalne
distinct(Saab, Model)
distinct(Saab, Marka)

# Losowe wybranie frakcji obserwacji ze zbioru:
sample_frac(Saab, 0.05, replace = TRUE) # 1%
sample_frac(Saab, 0.10, replace = TRUE) # 5%

# Losowe wybranie n obserwacji:
sample_n(Saab, 10, replace = T)
sample_n(Saab, 5, replace = T)

# Wybór wierszy w zależności od pozycji w bazie:
slice(Saab, 8:2)
slice(Saab, seq(1,nrow(Saab),8))

# Wybranie n pierwszych obserwacji według wieku:
top_n(Saab, 2, Cena.w.PLN) 
top_n(Saab, 4, Cena.w.PLN) 

3 Kolumny

3.1 Select()

3.1.1 Prosta selekcja

dane |> select(waga, wzrost) # wybranie 2 kolumn

dane |> select(wzrost:urodzony) # od ... do ...

dane |> 
  select(where(is.character)) # wybiera po typie 

dane |>
  select(imie,
         nazwisko,
         zatrudnienie = praca,
         miejsce_urodzenia = kraj) # lewa strona to nowa nazwa (zmiana nazwy)

3.1.2 Seleckja z regułami

  • starts_with("abc"): dopasowuje nazwy zaczynające się od „abc”.
  • ends_with("xyz"): dopasowuje nazwy kończące się na „xyz”.
  • contains("ijk"): dopasowuje nazwy zawierające „ijk”.
ff |> 
  select(starts_with("goals") & ends_with("nat"))

ff |> 
  select(starts_with("goals") | ends_with("nat"))

ff |> 
  select(contains("ts") | contains("na"))

3.1.3 Przykład

auta2012 |> 
  as_tibble() |> 
  select(Cena, Marka, Model)

3.2 mutate()

dodaje nową kolumne i coś oblicza

dane1 <-
  dane |> 
  mutate(wzrost_m = (wzrost / 100)) |> 
  mutate(BMI = waga / (wzrost_m ^ 2)) # nowa kolumna bmi z wynikiwm

dane1 |>
  mutate(jakie = BMI < 25.99 & BMI > 18.5) |>
  select(imie:stanow, plec, wzrost_m:jakie) # czy bmi jest w normie

Oprócz funkcji mutate() występuje funkcja transmute(), która zwraca tylko nowo utworzone cechy.

- .before deklaruje indeks zmiennej (w tablicy)

- .after deklaruje po któej zmiennej ma pokjawić się nowa zmienna

3.3 rename()

Jeśli chcesz zachować wszystkie istniejące zmienne i po prostu zmienić nazwy kilku, możesz użyć rename(). (Zmiana nazwy)

- dane |> rename(dni_urlpu = urlop, dochody = zarobki)

- auta2012 |> janitor::clean_names() |> names() -> zmienia nazwy na zgodne z najnowszą wersja tidyverse, czyli małe litery i _ zamiast .

3.4 relocate()

Funkcja relocate() umozliwia wygodne modyfikowanie położenia zmiennych.

dane |> 
  relocate(plec:urodzony, .after = praca) # kolumny od plec do urodzony wstawić po kolumnie praca

dane |> 
  relocate(contains("w"), .after = kraj) # wszystkie z litera "w" po kolumnie praca

3.4.1 Ćwiczenie

Zmień nazwę air_time na air_time_min, aby wskazać jednostki miary i przenieś ją na początek ramki danych.

flights |> 
  relocate(air_time_min = air_time, .before = 1)

Na podstawie zestawu dnaych flights oblicz faktycznie opóżnienie samolotu uwzględniająć opóżnienie/przeyspieszenie startu i lodawania w punkcie docelowym. Oblicz średnią prędkość samolotu w milach / godzinę. Wyświetl tylko wyniki dla nowych kolumn oraz kolumn wykorzystanych do obliczeń.

Przy pomocy funkcji cut utwórz zmienną kategoryczną typ, która zawiera następujące etykietu lotu c(“szybki”, ‘normalny’, “powolny”). Wskaż, jak dobrać odpowiednie wartości przedziałów.

fl1 <-
  flights |>
  mutate(
    opoznienie = dep_delay + arr_delay,
    predkosc = distance / air_time * 60,
    .keep = "used"
  ) # dodanie 2 kolumn

fl1 <-
  fl1 |>
  mutate(typ = cut(predkosc,
                   breaks = c(0, 300, 500, 800),
                   label = c("powolny", 'normalny', "szybki"))
         ) # podział na prędkość WAŻNE!

4 Pipe

  • CTRL + SHIFT + A- skrót kalwiaturowy poprawi składnie twojego kodu
  • CTRL + SHIFT + R - podział na sekcje w R
  • CTRL + SHIFT + M - |> (pipe)
obj1 <- rnorm(n = 100, mean = 3, sd = 4)
obj2 <- sample(obj1, size = 20, replace = T)
obj3 <- sort(obj2)
obj4 <- round(obj3, 1)
plot(obj4)

##### 2 przykład 
Przebieg <-
  filter(
    filter(
      arrange(
        filter(
          auta2012, 
          Marka == "Volkswagen"
          ), 
        desc(Cena.w.PLN)
        ), 
      Model == "Golf", Wersja == "IV"
      ),
  Przebieg.w.km < 50000
  )
out <- 
  rnorm(n = 100, mean = 3, sd = 4) |> 
  sample(x = _, size = 20, replace = T) |> 
  sort(x = _) |> 
  round(x = _, 1) |> 
  plot()

##### 2 przykład 
przebieg <-
  auta2012 %>%                                    # weź dane o autach
    filter(Marka == "Volkswagen") %>%             # pozostaw tylko Volkswageny
    arrange(Cena.w.PLN |> desc()) %>%             # posortuj malejąco po cenie
    filter(Model == "Golf", 
           Wersja == "IV") %>%                    # pozostał tylko Golfy VI
    filter(Przebieg.w.km < 50000)                 # pozostał tylko auta o małym przebiegu

przebieg |> as_tibble()

5 Grupy i agregacja

5.1 group_by()

Tworzy grupy danych na podstawie wartości w wybranych kolumnach. Wszystkie wiersze z tą samą wartością w kolumnie (lub kolumnach) grupowania zostaną umieszczone w jednej grupie.

dane |> 
  group_by(plec) |> 
  mutate(sr_wzrost =mean(wzrost), .keep = "used") |> 
  arrange(plec) #średni wzrost, różny dla każdej płci

5.2 summarize()

Funkcja summarize() jest przydatna w analizie danych do tworzenia skróconych podsumowań lub wskaźników, które pozwalają lepiej zrozumieć strukturę danych i przeprowadzać analizy.

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
# Tworzenie przykładowej ramki danych
data <- data.frame(
  group = c("A", "A", "B", "B", "A"),
  value = c(10, 20, 5, 15, 25)
)

# Grupowanie danych według kolumny "group"
data_grouped <- data %>% group_by(group)

# Obliczanie różnych statystyk w każdej grupie
summary_data <- data_grouped %>%
  summarize(
    mean_value = mean(value),
    total_value = sum(value),
    median_value = median(value)
  )

# Wynik
print(summary_data)
# A tibble: 2 × 4
  group mean_value total_value median_value
  <chr>      <dbl>       <dbl>        <dbl>
1 A           18.3          55           20
2 B           10            20           10

Nowy argument .by = funkcji summarize. Zastepuje on w pewien spsoób funckję group_by i nie działa w połączeniu z .groups. Musisz wybrać.

dane |>
  summarise(n      = n(),
            wzrost = mean(wzrost),
            .by = plec) # jedna zmienna

5.3 Grupowanie powielu zmiennych.

dane |> 
  group_by(plec, kraj) |> 
  summarise(n      = n(),
            wzrost = mean(wzrost))
# Otrzymalismy średni wzrost dla każdej mozliwej kombinacji zmiennych jakościowych plec i kraj.

Grupowanie można usuwać również za pomocą polecenia ungroup()

5.4 Ćwiczenia

df <- tibble(
  x = 1:5,
  y = c("a", "b", "a", "a", "b"),
  z = c("K", "K", "L", "L", "K")
)

df |>
  group_by(z) # grupowanie
# A tibble: 5 × 3
# Groups:   z [2]
      x y     z    
  <int> <chr> <chr>
1     1 a     K    
2     2 b     K    
3     3 a     L    
4     4 a     L    
5     5 b     K    
df |>
  arrange(y) # sortowanie
# A tibble: 5 × 3
      x y     z    
  <int> <chr> <chr>
1     1 a     K    
2     3 a     L    
3     4 a     L    
4     2 b     K    
5     5 b     K    
df |>
  group_by(y) |>
  summarize(mean_x = mean(x)) # grupowanie i średnia
# A tibble: 2 × 2
  y     mean_x
  <chr>  <dbl>
1 a       2.67
2 b       3.5 

Wybierz 3 ulubione modele samochodu, policz kilka statystyk (n, mean, var, max, min) dla zmiennej cena_w_pln oraz srednia moc silnika [km] zestawu danych auta2012. Zastosuj grupowanie po zmiennej model.

library(PogromcyDanych)
auta <- 
  auta2012 |> 
  as_tibble() |> 
  janitor::clean_names()

auta |>
  filter(model %in% c("X-90", "Aygo", "Civic")) |> 
  group_by(model) |> 
  summarise(
    n = n(),
    sred_cena = mean(cena_w_pln, na.rm = T),
    min_cena  = min(cena_w_pln, na.rm = T),
    max_cena  = max(cena_w_pln, na.rm = T),
    sred_km   = mean(km, na.rm = T) 
  )
# A tibble: 3 × 6
  model     n sred_cena min_cena max_cena sred_km
  <fct> <int>     <dbl>    <dbl>    <dbl>   <dbl>
1 Aygo    154    19987.     2999    37300    66.2
2 Civic  1703    21084.      400    77900   109. 
3 X-90      7     9728.     8299    11000    96.8

Wykorzystaj funkcje grepl(), aby określić procentowo ilość samochodów w których występuje odpowiednio:

  • klimatyzacja,
  • automatyczna skrzynia biegów
  • autoalarm
auta <- 
  auta2012 |> 
  as_tibble() |> 
  janitor::clean_names()

auta |>
  summarise(
    n       = n(),
    klima   = sum(grepl("klimatyzacja", wyposazenie_dodatkowe)),
    alarm   = sum(grepl("autoalarm", wyposazenie_dodatkowe)),
    a_biegi = sum(skrzynia_biegow == "automatyczna")
  ) |> 
  mutate(
    klima_proc = klima / n * 100,
    alarm_proc = alarm / n * 100,
    biegi_proc = a_biegi / n * 100
  )
# A tibble: 1 × 7
       n  klima alarm a_biegi klima_proc alarm_proc biegi_proc
   <int>  <int> <int>   <int>      <dbl>      <dbl>      <dbl>
1 207602 162960 91453   33888       78.5       44.1       16.3
  • Policz sumaryczny przebieg wszystkich samochodów. Następnie policz ile razy okrążono kulę ziemską uwzględniając te wszystkie przebiegi.
  • Wybierz tylko samochody marki Toyota i policz ich średni przebieg oraz średnią cenę w tyś zł w podziale na rodzaj paliwa.
  • sprawdzć, których modelach Toyota jest najczęściej stosowany jest olej napedowy (diesel)
rownik <- 40075.704

auta |>
  summarise(suma = sum(przebieg_w_km, na.rm = T)) |>
  mutate(okrazenia = suma / rownik)
# A tibble: 1 × 2
         suma okrazenia
        <dbl>     <dbl>
1 24730452691   617093.
auta |>
  filter(marka == "Toyota") |> 
  group_by(rodzaj_paliwa) |>
  summarise(
    n = n(),
    sr_przebieg = mean(przebieg_w_km, na.rm = T),
    sr_cena = mean(cena_w_pln, na.rm = T)
  )
# A tibble: 6 × 4
  rodzaj_paliwa              n sr_przebieg sr_cena
  <fct>                  <int>       <dbl>   <dbl>
1 benzyna                 3246     103971.  27479.
2 benzyna+LPG              237     171536.  21918.
3 etanol                     3     101430   14944.
4 hybryda                   50      48551.  63209.
5 naped elektryczny          5     111600   39540 
6 olej napedowy (diesel)  4073     132901.  40114.

Sprawdzć, w których modelach Toyoty najczęściej stosowany jest silnik napędzany na olej napedowy (diesel). Podpowiedzć: funkcja ungroup() będzie potrzeba oraz grupowanie po wielu zmiennych.

auta |>
  filter(marka == "Toyota") |>
  group_by(model, rodzaj_paliwa) |>
  summarise(
    n = n(), 
    .groups = "drop_last"
  ) |>
  mutate(
    sum = sum(n),
    proc = n / sum * 100
  ) |>
  slice_max(proc) |> # Wybiera wiersze z najwyższą wartością w kolumnie "proc" w obrębie każdej kombinacji "model" i "rodzaj_paliwa".
  ungroup() |>
  filter(rodzaj_paliwa == "olej napedowy (diesel)") |>
  arrange(proc |> desc())
# A tibble: 13 × 5
   model         rodzaj_paliwa              n   sum  proc
   <fct>         <fct>                  <int> <int> <dbl>
 1 Hiace         olej napedowy (diesel)     6     6 100  
 2 Hilux         olej napedowy (diesel)    59    61  96.7
 3 Avensis Verso olej napedowy (diesel)    99   105  94.3
 4 Land Cruiser  olej napedowy (diesel)   301   327  92.0
 5 Corolla Verso olej napedowy (diesel)   410   508  80.7
 6 Avensis       olej napedowy (diesel)  1182  1550  76.3
 7 Urban Cruiser olej napedowy (diesel)     9    12  75  
 8 Verso         olej napedowy (diesel)    39    58  67.2
 9 Picnic        olej napedowy (diesel)    15    23  65.2
10 Previa        olej napedowy (diesel)    28    44  63.6
11 RAV-4         olej napedowy (diesel)   566   897  63.1
12 Auris         olej napedowy (diesel)   252   435  57.9
13 Corolla       olej napedowy (diesel)   620  1191  52.1

Który przewoźnik ma największe średnie opóźnienia? Zestaw danych flights.

library(nycflights13)
flights
# A tibble: 336,776 × 19
    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
 1  2013     1     1      517            515         2      830            819
 2  2013     1     1      533            529         4      850            830
 3  2013     1     1      542            540         2      923            850
 4  2013     1     1      544            545        -1     1004           1022
 5  2013     1     1      554            600        -6      812            837
 6  2013     1     1      554            558        -4      740            728
 7  2013     1     1      555            600        -5      913            854
 8  2013     1     1      557            600        -3      709            723
 9  2013     1     1      557            600        -3      838            846
10  2013     1     1      558            600        -2      753            745
# ℹ 336,766 more rows
# ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
#   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
#   hour <dbl>, minute <dbl>, time_hour <dttm>
flights |> 
  mutate(delay = arr_delay + dep_delay) |> 
  group_by(carrier) |> 
  summarise(n = n(),
            nn = sum(!is.na(delay)), #nn" (liczba wierszy z opóźnieniem, pomijając brakujące dane) - ile razy sie spóźnił
            mean_delay = mean(delay, na.rm = T)) |> 
  slice_max(mean_delay)
# A tibble: 1 × 4
  carrier     n    nn mean_delay
  <chr>   <int> <int>      <dbl>
1 F9        685   681       42.1

Znajdź 5 lotów, które są najbardziej opóźnione w momencie odlotu (dep_delay) z każdego miejsca odlotu (origin).

flights |> 
  group_by(origin) |> 
  slice_max(dep_delay, n = 5) |> 
  select(origin, flight, dep_delay)
# A tibble: 15 × 3
# Groups:   origin [3]
   origin flight dep_delay
   <chr>   <int>     <dbl>
 1 EWR      3695      1126
 2 EWR       172       896
 3 EWR      3744       878
 4 EWR      1223       849
 5 EWR       172       845
 6 JFK        51      1301
 7 JFK      3535      1137
 8 JFK       177      1014
 9 JFK      3075      1005
10 JFK      2391       960
11 LGA      2119       911
12 LGA      2047       898
13 LGA       835       853
14 LGA      1435       812
15 LGA      2019       803

Jak opóźnienia różnią się w ciągu dnia?

out <-
  flights |>
  group_by(hour) |>
  summarise(m = mean(dep_delay, na.rm = T)) 


plot(x = out$hour, y = out$m, col="red", xlab = "Godzina", ylab="srednie opoznienia")

Wybierz 9-letni dowolny model samochodu i sprawdź, czy średnia cena zależy od kraju aktualnej rejestracji. Sprawdźć czy średnia cena samochodu Golf zalezy od roku produkcji.

a4 <-
  auta |> 
  filter(model == "A4") |>
  mutate(wiek = 2018 - rok_produkcji) |>
  filter(wiek == 9) |>
  group_by(kraj_aktualnej_rejestracji) |>
  summarise(n = n(),
            sr_cena = mean(cena_w_pln,
                           na.rm = T)) |>
  arrange(sr_cena)
#b 
golf <-
  auta |> 
  filter(model == "Golf") |> 
  group_by(rok_produkcji) |>
  summarise(n = n(),
            sr_cena = mean(cena_w_pln, na.rm = T),
            .groups = 'drop') |> 
  arrange(sr_cena |> desc())
golf
# A tibble: 36 × 3
   rok_produkcji     n sr_cena
           <dbl> <int>   <dbl>
 1          2011   320  68622.
 2          2012     8  54996.
 3          2010   138  54163.
 4          2009   177  42046.
 5          2008   337  37350.
 6          2007   285  33891.
 7          2006   192  29507.
 8          2005   238  28420.
 9          2004   337  24517.
10          2003   259  18896.
# ℹ 26 more rows
plot(golf$sr_cena, golf$rok_produkcji)

flights |> 
  group_by(carrier) |> 
  count(sort = T)
# A tibble: 16 × 2
# Groups:   carrier [16]
   carrier     n
   <chr>   <int>
 1 UA      58665
 2 B6      54635
 3 EV      54173
 4 DL      48110
 5 AA      32729
 6 MQ      26397
 7 US      20536
 8 9E      18460
 9 WN      12275
10 VX       5162
11 FL       3260
12 AS        714
13 F9        685
14 YV        601
15 HA        342
16 OO         32

6 Agregacje wielu zmiennych

6.1 across()

Funkcja across() umożliwia wykonywanie tych samych operacji na wielu zmiennych. pierwszy argument .cols() stosuje funkcje select() w celu identyfikacji odpowiednich zmiennych. Drugi argument funkcji to .fns które identyfikuje operacje, które mają zostać wykonane.

table1 |> 
  group_by(country) |> 
  summarise(s_cases = sum(cases, na.rm = T), 
            s_population = sum(population, na.rm = T))
table1 |> 
  group_by(country) |> 
  summarise(across(.cols = cases:population, 
                   .fns = sum))
diamonds |> 
  summarise(across(where(is.factor), n_distinct))
# A tibble: 1 × 3
    cut color clarity
  <int> <int>   <int>
1     5     7       8
diamonds |>
  group_by(cut) |>
  summarise(across(c(carat, depth, table),
                   mean, na.rm = T))
Warning: There was 1 warning in `summarise()`.
ℹ In argument: `across(c(carat, depth, table), mean, na.rm = T)`.
ℹ In group 1: `cut = Fair`.
Caused by warning:
! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
Supply arguments directly to `.fns` through an anonymous function instead.

  # Previously
  across(a:b, mean, na.rm = TRUE)

  # Now
  across(a:b, \(x) mean(x, na.rm = TRUE))
# A tibble: 5 × 4
  cut       carat depth table
  <ord>     <dbl> <dbl> <dbl>
1 Fair      1.05   64.0  59.1
2 Good      0.849  62.4  58.7
3 Very Good 0.806  61.8  58.0
4 Premium   0.892  61.3  58.7
5 Ideal     0.703  61.7  56.0
diamonds |>
  group_by(cut) |>
  summarise(across(
    .cols =  c(carat, depth, table),
    .fns = ~ mean(.x, na.rm = T)
  ))
# A tibble: 5 × 4
  cut       carat depth table
  <ord>     <dbl> <dbl> <dbl>
1 Fair      1.05   64.0  59.1
2 Good      0.849  62.4  58.7
3 Very Good 0.806  61.8  58.0
4 Premium   0.892  61.3  58.7
5 Ideal     0.703  61.7  56.0
Warning

Może być na kolokwium

library(gt)
library(tidyverse)
auta <- 
  auta2012 |> 
  as_tibble() |> 
  janitor::clean_names()

modele_forda <- 
  auta |> 
  filter(marka == "Ford") |> 
  count(model) |> 
  slice_max(n, n = 5) |> 
  mutate(model = as.character(model)) |> 
  pull(model)

param <- list(
  mean = ~ mean(.x, trim = 10, na.rm = T),
  sd = ~ sd(.x, na.rm = T),
  min = ~ min(.x, na.rm = T),
  max =~ max(.x, na.rm = T)

)

auta |> 
  filter(marka == "Ford", model %in% modele_forda) |> 
  select(marka, model, cena_w_pln, km, pojemnosc_skokowa) |> 
  mutate(ratio = cena_w_pln/km) |> 
  group_by(model) |> 
  mutate(m_ratio = mean(ratio, na.rm = T)) |> 
  summarise(n=n(),
            across(.cols = cena_w_pln:m_ratio,
                    .fns = param,
                   .names = "{.col}/{.fn}")) |> 
  ungroup() |> 
  pivot_longer(cols = `cena_w_pln/mean`:`m_ratio/max`,
               names_to = "param",
               values_to = "value") |> 
  mutate(value = round(value, 1)) |> 
  arrange(param, model) |> 
  separate(param, into = c("parametr", "stats"), sep = "/") |> 
  pivot_wider(names_from = stats, values_from = value) |>
  gt::gt()
#zmaiana _ na . w nazwach .fns = mean, na.rm=T)) 
# policzenie średniej dla każdej podanej kolumny .fns = ~mean(.x, trim = 10, na.rm=T)) 
# robi to samo(.x) <- dla wszystkich, trim ucina 10% warotści odstających
out <-
  diamonds |>
  mutate(across(
    .cols =  where(is.numeric),
    .fns = ~ (.x - mean(.x)) / sd(.x)
  ))

out
# A tibble: 53,940 × 10
   carat cut       color clarity  depth  table  price     x     y     z
   <dbl> <ord>     <ord> <ord>    <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl>
 1 -1.20 Ideal     E     SI2     -0.174 -1.10  -0.904 -1.59 -1.54 -1.57
 2 -1.24 Premium   E     SI1     -1.36   1.59  -0.904 -1.64 -1.66 -1.74
 3 -1.20 Good      E     VS1     -3.38   3.38  -0.904 -1.50 -1.46 -1.74
 4 -1.07 Premium   I     VS2      0.454  0.243 -0.902 -1.36 -1.32 -1.29
 5 -1.03 Good      J     SI2      1.08   0.243 -0.902 -1.24 -1.21 -1.12
 6 -1.18 Very Good J     VVS2     0.733 -0.205 -0.902 -1.60 -1.55 -1.50
 7 -1.18 Very Good I     VVS1     0.384 -0.205 -0.902 -1.59 -1.54 -1.51
 8 -1.13 Very Good H     SI1      0.105 -1.10  -0.901 -1.48 -1.42 -1.43
 9 -1.22 Fair      E     VS2      2.34   1.59  -0.901 -1.66 -1.71 -1.49
10 -1.20 Very Good H     VS1     -1.64   1.59  -0.901 -1.54 -1.47 -1.63
# ℹ 53,930 more rows

7 Operacje na wierszach

7.1 rowwise()

df <- tibble(x = 1:4, y = 3:6, z = 6:9)

df |>
  mutate(m = mean(c(x, y, z))) # liczy pionowo
# A tibble: 4 × 4
      x     y     z     m
  <int> <int> <int> <dbl>
1     1     3     6  4.83
2     2     4     7  4.83
3     3     5     8  4.83
4     4     6     9  4.83
df |>
  rowwise() |>
  mutate(m = mean(c(x, y, z))) # liczy poziomo
# A tibble: 4 × 4
# Rowwise: 
      x     y     z     m
  <int> <int> <int> <dbl>
1     1     3     6  3.33
2     2     4     7  4.33
3     3     5     8  5.33
4     4     6     9  6.33

7.2 Statystyki podsumowujące

suma każdego wiersza

df <- tibble(id = 1:6, w = 10:15, x = 20:25, y = 30:35, z = 40:45)
df |> 
  rowwise(id) |> 
  mutate(total = sum(w,x,y,z))
# A tibble: 6 × 6
# Rowwise:  id
     id     w     x     y     z total
  <int> <int> <int> <int> <int> <int>
1     1    10    20    30    40   100
2     2    11    21    31    41   104
3     3    12    22    32    42   108
4     4    13    23    33    43   112
5     5    14    24    34    44   116
6     6    15    25    35    45   120
df |> 
  rowwise(id) |> 
  summarise(total = sum(w,x,y,z), .groups = 'drop')
# A tibble: 6 × 2
     id total
  <int> <int>
1     1   100
2     2   104
3     3   108
4     4   112
5     5   116
6     6   120

7.3 przykłady do analizy

ff <- read_csv2(file = "dane/footballers2.csv")
ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
Rows: 258 Columns: 24
── Column specification ────────────────────────────────────────────────────────
Delimiter: ";"
chr  (3): market_value, popularity, name
dbl (21): age, height, weight, goals_CL, goals_UEFA, goals_cups, goals_top5l...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
ff |>
  rowwise(name) |>
  mutate(goals_total = sum(c_across(contains("goals") &
                                      !goals_top5l),
                           na.rm = T),
         .keep = "used")
# A tibble: 258 × 7
# Rowwise:  name
   goals_CL goals_UEFA goals_cups goals_rest goals_nat name         goals_total
      <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <chr>              <dbl>
 1        5          0          7          0         0 bojan krkic           12
 2       25          0         16          0        14 lionel messi          55
 3        4          0          6          0         1 pedro                 11
 4        0          0          0          0         0 jeffren                0
 5        8          8          2          0        44 david villa           62
 6       13          0          2          0        11 benzema               26
 7        2          0          1          5         7 higuain               15
 8       23          0         11          0        25 cristiano             59
 9        4          1          0          0         9 nilmar                14
10        3          2          6          0         3 rossi                 14
# ℹ 248 more rows
ff |>
  rowwise(name) |>
  mutate(goals_total = sum(c_across(contains("goals") &
                                      !goals_top5l),
                           na.rm = T),
         .keep = "used") |> 
  ungroup() |> 
  filter(goals_total > 0) |>                   # nie dzielimy przez zero.
  mutate(across(.cols = goals_CL:goals_nat, 
                .fns = ~ .x / goals_total)
  )
# A tibble: 227 × 7
   goals_CL goals_UEFA goals_cups goals_rest goals_nat name         goals_total
      <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <chr>              <dbl>
 1    0.417     0          0.583       0        0      bojan krkic           12
 2    0.455     0          0.291       0        0.255  lionel messi          55
 3    0.364     0          0.545       0        0.0909 pedro                 11
 4    0.129     0.129      0.0323      0        0.710  david villa           62
 5    0.5       0          0.0769      0        0.423  benzema               26
 6    0.133     0          0.0667      0.333    0.467  higuain               15
 7    0.390     0          0.186       0        0.424  cristiano             59
 8    0.286     0.0714     0           0        0.643  nilmar                14
 9    0.214     0.143      0.429       0        0.214  rossi                 14
10    0         0          0           0.944    0.0556 ruben                 18
# ℹ 217 more rows

Zwróć uwagę, gdzie stosujemy across i c_across, czy widzisz różnice. across współpracuje z funkcjami dplyr np. mutate, summarise, natomiast c_across z funcjami podstawowymi np.: sum, mean.

7.4 Funkcje agregujace po wierszach

Grupowanie przy pomocy rowwise, jest wygodne oraz zapenwia nam pełną kontrolę pisania kodu. Natomiast dostepne są prostsze funkcje podsumowujaće rowSums() i rowMeans().

ff |> 
  mutate(total = rowSums(pick(contains("goals") & 
                                !goals_top5l)), 
         .keep = "used")
# A tibble: 258 × 6
   goals_CL goals_UEFA goals_cups goals_rest goals_nat total
      <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <dbl>
 1        5          0          7          0         0    12
 2       25          0         16          0        14    55
 3        4          0          6          0         1    11
 4        0          0          0          0         0     0
 5        8          8          2          0        44    62
 6       13          0          2          0        11    26
 7        2          0          1          5         7    15
 8       23          0         11          0        25    59
 9        4          1          0          0         9    14
10        3          2          6          0         3    14
# ℹ 248 more rows
ff |>
  mutate(mean = rowMeans(pick(contains("goals") &
                                !goals_top5l)), 
         .keep = "used")
# A tibble: 258 × 6
   goals_CL goals_UEFA goals_cups goals_rest goals_nat  mean
      <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <dbl>
 1        5          0          7          0         0   2.4
 2       25          0         16          0        14  11  
 3        4          0          6          0         1   2.2
 4        0          0          0          0         0   0  
 5        8          8          2          0        44  12.4
 6       13          0          2          0        11   5.2
 7        2          0          1          5         7   3  
 8       23          0         11          0        25  11.8
 9        4          1          0          0         9   2.8
10        3          2          6          0         3   2.8
# ℹ 248 more rows

8 CHEATSHEET

CHEATSHEET - 1

Base R

Data import