class: center, middle, inverse, title-slide .title[ # Podstawy programowania ] .subtitle[ ## Przetwarzanie danych ] .author[ ### © Łukasz Wawrowski ] --- # Zestaw analityka - tidyverse .pull-left[ ``` install.packages("tidyverse") ``` - readxl - wczytywanie plików Excela - haven - wczytywanie plików SAS, SPSS, Stata - jsonlite - wczytywanie JSON - xml2 - wczytywanie XML - httr - dostęp do stron html - rvest - web scraping - DBI - dostęp do baz danych - hms - operacje na czasie dnia - blob - przechowywanie danych binarnych - magrittr - przetwarzanie potokowe `%>%` - glue - łączenie tekstów ] .pull-right[ ``` library("tidyverse") ``` - dplyr - przetwarzanie danych tabelarycznych - forcats - operacje na czynnikach - ggplot2 - wykresy - lubridate - operacje na datach - purrr - programowanie funkcyjne - readr - wczytywanie plików tekstowych - stringr - operacje na tekstach - tibble - nowoczesny data.frame - tidyr - porządkowanie danych ] [Strona projektu Tidyverse](https://www.tidyverse.org/) --- # Instalacja vs. wczytywanie  --- # Struktura projektu ``` project/ ├── data/ ├── docs/ ├── figs/ ├── output/ ├── 01_input.R └── 02_analysis.R ``` --- # Pliki tekstowe i csv Pakiet _readr_: - `read_delim()` - ogólna funkcja do plików tekstowych - `read_csv()` - uwzględnia nagłówek, separator kolumn to przecinek, separator miejsc dziesiętnych to kropka - `read_csv2()` - uwzględnia nagłówek, separator kolumn to średnik, separator miejsc dziesiętnych to przecinek -- R dostarcza także funkcje `read.csv()`, `read.csv2()`, `read.delim()`, które są starszymi odpowiednikami funkcji z pakietu _readr_. --- # Pliki Excela Pakiet _readxl_: - `read_excel()` - określa format na podstawie pliku - `read_xls()` - wczytuje pliki .xls - `read_xlsx()` - wczytuje pliki .xlsx --- # Pliki SAS, SPSS, Stata Pakiet _haven_: - `read_sas()` - wczytuje pliki .sas - `read_sav()` - wczytuje pliki .sav - `read_stata()` - wczytuje pliki .dta --- ## Wczytywanie danych o formacie R - `load("zbior.RData")` - `dane <- readRDS("zbior.RDS")` --- ## Zapisywanie danych o formacie R Zapisywanie do formatu R: - `save(dane, file = "zbior.RData")` - `save(dane1, dane2, file = "zbior.RData")` - `saveRDS(dane, file = "zbior.RDS")` --- # Zapisywanie danych Zapisywanie do pliku tekstowego (txt, csv): - `write_csv(x = obiekt, file = "plik.csv")` - `write_csv2(x = obiekt, file = "plik.csv")` Zapisywanie do pliku Excela z pakietem _openxlsx_: - `write.xlsx(x = obiekt, file = "plik.xlsx")` --- # Wczytanie zbioru danych Importujemy zbiór danych dotyczący wyników wyborów w 2025 roku. Plik z danymi: http://wawrowski.edu.pl/data/wybory2025.csv [Źródło](https://prezydent2025.pkw.gov.pl/prezydent2025/pl/dane_w_arkuszach) Alternatywnie: [(https://github.com/lwawrowski/blog-quarto/tree/master/_site/data)](https://github.com/lwawrowski/blog-quarto/tree/master/_site/data) --- class: inverse # Zadanie Wywołaj funkcję `summary()` na wczytanym zbiorze danych.
−
+
02
:
00
--- # Pakiet _janitor_ Surowe dane zwykle nie posiadają nazw kolumn przystosowanych do przetwarzania przez komputer - nazwy zmiennych nie powinny zawierać polskich liter i spacji - nazwy zmiennych nie powinny zaczynać się od liczby Te problemy rozwiązuje pakiet _janitor_ (dozorca, woźny) i funkcja `clean_names()`: ```r zbior <- janitor::clean_names(zbior) ``` - funkcja ta zamienia wielkie litery na małe, spacje na podkreślniki i znaki transliteruje do ASCII. --- class: inverse # Zadanie Wczytaj do R plik movies: http://wawrowski.edu.pl/data/movies.csv i wywołaj na nim funkcję `summary()`.
−
+
05
:
00
--- # Rozpoczynanie pracy z R .pull-left[ __Nowy projekt__ 1. Otwórz RStudio 2. Stwórz nowy projekt 3. Przenieś dane do folderu projektu 4. Otwórz nowy skrypt R 5. (Zainstaluj i) wczytaj biblioteki 6. Wczytaj dane 7. Analizuj ] .pull-right[ __Istniejący projekt__ 1. Otwórz RStudio 2. Otwórz istniejący skrypt R 3. Wczytaj biblioteki 4. Wczytaj dane 5. Kontyuuj analizę ] --- class: inverse # Zadanie Wczytaj zbiór danych dotyczący wyników wyborów.
−
+
02
:
00
--- # R base vs. tidyverse **Podstawowe funkcje R** ``` r widest_petals <- by(iris, INDICES = iris$Species, FUN = function(x){ x[x$Petal.Width == max(x$Petal.Width), ] }) do.call(rbind, widest_petals) ``` -- **Funkcje pakietu tidyverse** ``` r iris %>% group_by(Species) %>% filter(Petal.Width == max(Petal.Width)) ``` [źródło](https://tavareshugo.github.io/data_carpentry_extras/base-r_tidyverse_equivalents/base-r_tidyverse_equivalents.html) --- <center><img src="img/magrittr.png" height="600"></center> --- # Przetwarzanie potokowe Sekwencja zdarzeń - w życiu ``` obudź się %>% wyjdź z łóżka %>% skorzystaj z łazienki %>% zjedź śniadanie %>% ubierz się %>% idź do pracy ``` [źródło](https://twitter.com/WeAreRLadies/status/1172576445794803713) --- # Przetwarzanie potokowe Użycie operatora **pipe**: `%>%` (łącznik) ułatwia zarządzanie kodem i pisanie czytelnej składni poprzez wykorzystanie istniejących struktur danych: Nowe obiekty ``` r iris_3kol <- select(iris, Petal.Length, Petal.Width, Species) iris_3kol_wymiar <- mutate(iris_3kol, petal_wymiar=Petal.Length+Petal.Width) iris_3kol_wymiar_setosa <- filter(iris_3kol_wymiar, Species=="setosa") ``` -- Zagnieżdżanie ``` r iris_setosa <- filter(mutate(select(iris, Petal.Length, Petal.Width, Species), petal_wymiar=Petal.Length+Petal.Width), Species=="setosa") ``` --- # Przetwarzanie potokowe Przetwarzanie potokowe ``` r iris_setosa <- iris %>% select(Petal.Length, Petal.Width, Species) %>% mutate(petal_wymiar=Petal.Length+Petal.Width) %>% filter(Species=="setosa") ``` -- Znak `%>%` oznacza, że jako argument wejściowy `data` w kolejnej funkcji zostanie wpisany wynik działania wcześniejszej funkcji. Skrót klawiszowy: ctrl + shift + m --- # Wybrane funkcje - `select()` - wybór zmiennych - `filter()` - wybór obserwacji - `mutate()` - tworzenie/modyfikacja zmiennej - `rename()` - zmiana nazwy zmiennej - `count()` - zliczanie obserwacji - `summarise()` - podsumowania danych - `group_by()` - operowanie na grupach - `arrange()` - sortowanie --- # Filtrowanie - `filter()` Porównywanie: - `=` symbol przypisania (nie jest używany w filtrowaniu) - `==` symbol porównania (jest równe) - `!=` symbol negacji (jest różne) - `>` i `<` większe i mniejsze - `>=` i `<=` większe lub równe i mniejsze lub równe Operatory: - `&` - i - `|` - lub (alternatywa) - `%in%` - wartość ze zbioru - `!` - negacja --- class: inverse # Zadanie Utwórz zbiór danych zawierający filmy, które są filmami akcji, miały swoją premierę po 2010 roku i trwały co najmniej 120 minut lub miały ocenę powyżej 8.0. Alternatywa ma dotyczyć tylko dwóch ostatnich warunków.
−
+
05
:
00
--- # Braki danych Brak danych jest oznaczany jako `NA`. Jest to wartość nieliczbowa i **nie można** jej porównywać w następujący sposób: - `zmienna == NA` - `zmienna != NA` - `zmienna == "NA"` - `zmienna != "NA"` tylko z wykorzystaniem funkcji `is.na()`: - `is.na(zmienna)` - `!is.na(zmienna)` Funkcja `complete.cases()` lub `drop_na()` służy do identyfikacji obserwacji, które nie zawierają braków danych w całym zbiorze danych. --- class: inverse # Zadanie Ile obwodów głosowania znajduje się w Poznaniu?
−
+
05
:
00
--- # Wybieranie kolumn - `select()` Wybór kolumn, które mają się znaleźć w nowym zbiorze: ``` r iris2 <- iris %>% select(Species, Petal.Length, Petal.Width) ``` Które nie mają się znaleźć w nowym zbiorze: ``` r iris2 <- iris %>% select(-Petal.Length, -Petal.Width) ``` Które mają znaleźć się w nowym zbiorze z nową nazwą: ``` r iris2 <- iris %>% select(gatunek=Species, Petal.Length, Petal.Width) ``` --- # Kolejność w przetwarzaniu potokowym .pull-left[ DOBRZE ``` r iris %>% filter(Petal.Width < 0.5) %>% select(Species, Sepal.Length, Sepal.Width) ``` ``` ## Species Sepal.Length Sepal.Width ## 1 setosa 5.1 3.5 ## 2 setosa 4.9 3.0 ## 3 setosa 4.7 3.2 ## 4 setosa 4.6 3.1 ## 5 setosa 5.0 3.6 ## 6 setosa 5.4 3.9 ``` ] -- .pull-right[ ŹLE ``` r iris %>% select(Species, Sepal.Length, Sepal.Width) %>% filter(Petal.Width < 0.5) ``` ``` ## Error in `filter()`: ## ℹ In argument: `Petal.Width < 0.5`. ## Caused by error: ## ! object 'Petal.Width' not found ``` ] --- # Zmiana nazwy - `rename()` Zapis w konwencji `rename(nowa_nazwa=stara_nazwa)` Można także wykorzystać funkcję `select()` - zmieniając nazwę podczas wybierania zmiennych Funkcja `rename_with()` umożliwia zmianę nazw z wykorzystaniem funkcji np. zamieniając nazwy kolumn na zapisane wielkimi literami. --- class: inverse # Zadanie Sprawdź jak działa funkcja `rename` - zmień nazwę kolumny w zbiorze danych z `siedziba` na `siedziba_komisji`.
−
+
03
:
00
--- # Nowa zmienna/modyfikacja - `mutate()` ``` r iris <- iris %>% mutate(petal=Petal.Length+Petal.Width, sepal=Sepal.Length+Sepal.Width, iloraz=petal/sepal) ``` Funkcje: - `mutate_all` - modyfikacja wszystkich zmiennych według podanej formuły - `mutate_if` - modyfikacja wszystkich zmiennych spełniających warunek - `mutate_at` - modyfikacja wszystkich wskazanych zmiennych są zastępowane przez jedną funkcję `across`. --- class: inverse # Zadanie W zbiorze dotyczącym wyborów stwórz nowe zmienne, które będą zawierały procentowy wynik kandydatów. Gdzie była największa różnica pomiędzy wybranymi kandydatami?
−
+
08
:
00
--- # Warunkowe tworzenie zmiennej Funkcje pozwalające na warunkowe tworzenie nowej zmiennej: - `if_else(condition, true, false)` - `case_when(condtion1 ~ value1, condition2 ~ value2, .default = value3)` --- class: inverse # Zadanie Ile obwodów głosowania miało frekwencję powyżej 80%?
−
+
03
:
00
--- ## Podsumowanie - `summarise()` i `summarize()` ``` r iris %>% summarise(liczebnosc=n(), srednia_pl=mean(Petal.Length), mediana_sl=median(Sepal.Length)) ``` ``` ## liczebnosc srednia_pl mediana_sl ## 1 150 3.758 5.8 ``` --- class: inverse # Zadanie Ile wynosiła średnia, mediana i odchylenie standardowe wartości frekwencji?
−
+
05
:
00
--- # Grupowanie - `group_by()` Najlepiej działa w połączeniu z `summarise()`: ``` r iris %>% group_by(Species) %>% summarise(liczebnosc=n(), srednia_pl=mean(Petal.Length)) ``` ``` ## # A tibble: 3 × 3 ## Species liczebnosc srednia_pl ## <fct> <int> <dbl> ## 1 setosa 50 1.46 ## 2 versicolor 50 4.26 ## 3 virginica 50 5.55 ``` --- # Liczebności - `count()` Jeżeli chcemy tylko wyznaczyć liczebności grup to wystarczy funkcja `count()`: ``` r iris %>% count(Species) ``` ``` ## Species n ## 1 setosa 50 ## 2 versicolor 50 ## 3 virginica 50 ``` --- # Sortowanie - `arrange()` Sortuje podane kolumny w porządku rosnącym. ``` r iris %>% arrange(Sepal.Length, Sepal.Width) %>% head() ``` ``` ## Sepal.Length Sepal.Width Petal.Length Petal.Width Species ## 1 4.3 3.0 1.1 0.1 setosa ## 2 4.4 2.9 1.4 0.2 setosa ## 3 4.4 3.0 1.3 0.2 setosa ## 4 4.4 3.2 1.3 0.2 setosa ## 5 4.5 2.3 1.3 0.3 setosa ## 6 4.6 3.1 1.5 0.2 setosa ``` Posortowanie w porządku malejącym wymaga użycia funkcji `desc()` w odniesieniu do wybranej kolumny. --- class: inverse # Zadanie Oblicz liczbę komisji w poszczególnych województwach oraz średnią liczbę nieważnych głosów.
−
+
05
:
00
--- class: inverse # Zadanie
−
+
10
:
00
W jakich krajach i miastach za granicą utworzono najwięcej obwodów głosowania? --- # Łączenie danych  [źródło](https://rpubs.com/williamsurles/293454) --- class: inverse # Zadanie Po wczytaniu zbioru danych [gus.RData](http://wawrowski.edu.pl/data/gus.RData) połącz ze sobą zbiory danych zawierające informacje o liczbie przedsiębiorstw na 10 tys. mieszkańców (zbiór _pod_10tys_), stopie bezrobocia (zbiór _bezrobocie_) oraz wynagrodzeniu (zbiór _wyn_).
−
+
10
:
00
--- # Szeroka i długa reprezentacja danych  [źródło](https://www.datasciencemadesimple.com%2Freshape-in-r-from-wide-to-long-from-long-to-wide) --- # Animacja  [źródło](https://github.com/gadenbuie/tidyexplain) --- # Zbiór _iris_ ``` r head(iris) ``` ``` ## Sepal.Length Sepal.Width Petal.Length Petal.Width Species ## 1 5.1 3.5 1.4 0.2 setosa ## 2 4.9 3.0 1.4 0.2 setosa ## 3 4.7 3.2 1.3 0.2 setosa ## 4 4.6 3.1 1.5 0.2 setosa ## 5 5.0 3.6 1.4 0.2 setosa ## 6 5.4 3.9 1.7 0.4 setosa ``` --- # Wide -> long - `pivot_longer()` ``` r iris_long <- iris %>% mutate(id=1:nrow(iris)) %>% pivot_longer(Sepal.Length:Petal.Width) head(iris_long) ``` ``` ## # A tibble: 6 × 4 ## Species id name value ## <fct> <int> <chr> <dbl> ## 1 setosa 1 Sepal.Length 5.1 ## 2 setosa 1 Sepal.Width 3.5 ## 3 setosa 1 Petal.Length 1.4 ## 4 setosa 1 Petal.Width 0.2 ## 5 setosa 2 Sepal.Length 4.9 ## 6 setosa 2 Sepal.Width 3 ``` --- # Long -> wide - `pivot_wider()` ``` r iris_wide <- iris_long %>% pivot_wider() head(iris_wide) ``` ``` ## # A tibble: 6 × 6 ## Species id Sepal.Length Sepal.Width Petal.Length Petal.Width ## <fct> <int> <dbl> <dbl> <dbl> <dbl> ## 1 setosa 1 5.1 3.5 1.4 0.2 ## 2 setosa 2 4.9 3 1.4 0.2 ## 3 setosa 3 4.7 3.2 1.3 0.2 ## 4 setosa 4 4.6 3.1 1.5 0.2 ## 5 setosa 5 5 3.6 1.4 0.2 ## 6 setosa 6 5.4 3.9 1.7 0.4 ``` --- class: inverse # Zadanie Stwórz zbiór danych, który będzie zawierał średni wynik kandydatów w przekroju województw, na następnie zamień reprezentację tego zbioru na reprezentację długą.
−
+
10
:
00
--- class: inverse, center, middle # Pytania?