Ustawianie ścieżki

Orientujemy się gdzie jesteśmy. Można odpalić też eksploratora Windows i stamtąd sięgnąć po ścieżkę, wklejając ją do polecenia (funkcji): setwd("...")

getwd() # orientujemy się gdzie jesteśmy
## [1] "C:/Users/Maluchnik/Documents/Statystyka1_R/materialy/Zaj_3"
# setwd(...) always a good choice...

# \ (backslash - Windows) vs / (slash - reszta świata)
list.files() # == dir()
## [1] "dane"             "grafika"          "rsconnect"        "SQL_query_in_R.R"
## [5] "styles.css"       "Zaj3 - Copy.html" "Zaj3.html"        "Zaj3.Rmd"
# opowiedzieć o alternatywnych sposobach ustawiania working directory poprzez wyklikanie prawego dolnego okna ->

# Ciekawostka - alternatywa dla ukośników:
file.path("C:", "Users", "Maluchnik", "Documents")
## [1] "C:/Users/Maluchnik/Documents"



Wczytywanie danych

Ramki predefiniowane

Lista baz danych zawartych w pakiecie {dataset} ujawni nam się po użyciu polecenia: data().

Lista baz danych z wszystkich aktywnych pakietów (nie tylko {dataset}) odpalamy poleceniem: data(package = .packages(all.available = TRUE))

# z poprzednich zajęć znamy co najmniej jedną z poniższych ramek
head(iris, 3)
##   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
head(mtcars, 3)
##                mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4     21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710    22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
# niektóre znajdują się w innych pakietach, zatem najpierw wczytujemy pakiet go zawierający 
library(ggplot2)
# a następnie
head(diamonds, 3) # -> nie ma w środowisku
## # A tibble: 3 × 10
##   carat cut     color clarity depth table price     x     y     z
##   <dbl> <ord>   <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1  0.23 Ideal   E     SI2      61.5    55   326  3.95  3.98  2.43
## 2  0.21 Premium E     SI1      59.8    61   326  3.89  3.84  2.31
## 3  0.23 Good    E     VS1      56.9    65   327  4.05  4.07  2.31
data(diamonds) # -> Promise? Promise what?
diamonds[1:5,1:5] # -> jest po pierwszej próbie użycia zbioru :D
## # A tibble: 5 × 5
##   carat cut     color clarity depth
##   <dbl> <ord>   <ord> <ord>   <dbl>
## 1  0.23 Ideal   E     SI2      61.5
## 2  0.21 Premium E     SI1      59.8
## 3  0.23 Good    E     VS1      56.9
## 4  0.29 Premium I     VS2      62.4
## 5  0.31 Good    J     SI2      63.3
# Inny przykład ...
dane_KolorOczuIWlosow = HairEyeColor # studentów statystki (kobiet i mężczyzn)
str(dane_KolorOczuIWlosow)
##  'table' num [1:4, 1:4, 1:2] 32 53 10 3 11 50 10 30 10 25 ...
##  - attr(*, "dimnames")=List of 3
##   ..$ Hair: chr [1:4] "Black" "Brown" "Red" "Blond"
##   ..$ Eye : chr [1:4] "Brown" "Blue" "Hazel" "Green"
##   ..$ Sex : chr [1:2] "Male" "Female"
iris <-  iris
mtcars <-  mtcars




.txt

Najpopularniejszy format danych wczytywanych do R to dane tekstowe. Jest to format prosty i uniwersalny - cała informacja zakodowana jest w znakach widocznych z poziomu Notepad’a, a pliki da się odczytać w różnych programach na każdym dostępnym systemie operacyjnym.

Klasyfikacja typów plików może zostać dokonana na podstawie sposobu organizacji kolumn, mamy zatem:

  • pliki rozdzielane separatorem (średnik, przecinek, znak pionowej linii, etc.)

  • pliki o stałej szerokości kolumn (fixed width column)

Zawsze, używając po raz pierwszy jakiejś funkcji, przejrzyjmy wcześniej jej dokumentację ?read.table (lub help(package="read.table"). read.table jest to uogólniona funkcja do wczytywania wielu typów formatów plików tekstowych.

miasta <- read.table("dane/cities.txt", # nazwa pliku wraz z rozszerzeniem 
                     header = TRUE, # pierwsza kolumna jako nagłówek?
                     sep = ",", # separator kolumn
                     dec = ".") # znak oddzielający część całkowitą od dziesiętnej

Sprawdzenie danych (i utrwalenie podstawowych funkcji rozruchowych - do rozeznania się w ramce bez niepotrzebnego print’owania w konsoli)

is.data.frame(miasta) # czy to data.frame?
## [1] TRUE
head(miasta,3) # wyrzucenie do konsoli pierwszych 3 wierszy
##   Country             City       AccentCity Region Population Latitude
## 1      ad andorra la vella Andorra la Vella     07      20430 42.50000
## 2      ad          canillo          Canillo     02       3292 42.56667
## 3      ad           encamp           Encamp     03      11224 42.53333
##   Longitude
## 1  1.516667
## 2  1.600000
## 3  1.583333
tail(miasta,3) # wyrzucenie do konsoli ostatnich 3 wierszy
##       Country           City     AccentCity Region Population  Latitude
## 47978      zw       shurugwi       Shurugwi     07      17107 -19.66667
## 47979      zw victoria falls Victoria Falls     00      36702 -17.93333
## 47980      zw     zvishavane     Zvishavane     07      79876 -20.33333
##       Longitude
## 47978  30.00000
## 47979  25.83333
## 47980  30.03333
is.numeric(miasta$Population) # upewnienie się co do typu danych konkretnej zmiennej
## [1] TRUE
str(miasta) # struktura danych
## 'data.frame':    47980 obs. of  7 variables:
##  $ Country   : chr  "ad" "ad" "ad" "ad" ...
##  $ City      : chr  "andorra la vella" "canillo" "encamp" "la massana" ...
##  $ AccentCity: chr  "Andorra la Vella" "Canillo" "Encamp" "La Massana" ...
##  $ Region    : chr  "07" "02" "03" "04" ...
##  $ Population: int  20430 3292 11224 7211 15854 2553 8020 603687 1137376 543942 ...
##  $ Latitude  : num  42.5 42.6 42.5 42.5 42.5 ...
##  $ Longitude : num  1.52 1.6 1.58 1.52 1.53 ...
summary(miasta) # podsumowanie zmiennych
##    Country              City            AccentCity           Region         
##  Length:47980       Length:47980       Length:47980       Length:47980      
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##    Population          Latitude        Longitude      
##  Min.   :       7   Min.   :-54.80   Min.   :-179.50  
##  1st Qu.:    3732   1st Qu.: 14.65   1st Qu.: -41.68  
##  Median :   10779   Median : 39.13   Median :  19.90  
##  Mean   :   47720   Mean   : 30.62   Mean   :  14.67  
##  3rd Qu.:   27990   3rd Qu.: 47.87   3rd Qu.:  58.41  
##  Max.   :31480498   Max.   : 78.93   Max.   : 179.32

Czy moglibyśmy opuścić argumenty funkcji read.table?

miasta2 <- read.table("dane/cities.txt") 

Nie działa, bo domyślnie argumenty uzupełnione w następujący sposób: header = FALSE, sep = "", dec = "."

.csv

Zajrzyjmy do dokumentacji: ?read.csv. Jest to funkcja z rodziny read.table służąca do wczytywania danych z pliku csv (tekstowy rozdzielany przecinkami)

daneusa <- read.csv("dane/daneusa.csv") # wczytanie

Domyślne założenia funkcji:

  • separator -> sep = ","

  • znak dziesiętny -> dec = "."

  • header = FALSE -> plik zawiera nazwy kolumn w pierwszym wierszu (nagłówek)

jeśli jest inaczej, można użyć odpowiednich dodatkowych argumentów funkcji:

daneusa <- read.csv("dane/daneusa.csv", 
                    sep = ",",
                    dec = ".",
                    header = TRUE)

Jest też funkcja read.csv2(), (stworzona dla Europy kontynentalnej), która ma inne domyślne parametry tj.: sep = " oraz ", dec = ",".

Co by się stało, gdybyśmy skorzystali z niej do wczytania tego pliku?

daneusa <- read.csv2("dane/daneusa.csv")

warto zwrócić na to uwagę w Global Environment. Inny separator kolumn spowodował, że R nie rozróżnia kolumn

Wróćmy więc do poprzedniej funkcji i wczytajmy ponownie (poprawnie) dane:

daneusa <- read.csv("dane/daneusa.csv")
class(daneusa); str(daneusa)
## [1] "data.frame"
## 'data.frame':    35072 obs. of  29 variables:
##  $ UMARSTAT: chr  "Never married" "Separated" "Married_live together" "Divorced" ...
##  $ UCUREMP : chr  "No" "Yes" "No" "No" ...
##  $ UCURNINS: chr  "Yes" "No" "No" "Yes" ...
##  $ USATMED : chr  "Very satisfied" "Very satisfied" "Very satisfied" "Little dissatisfied" ...
##  $ URELATE : int  2 2 5 4 0 1 0 1 0 0 ...
##  $ REGION  : chr  "Midwest" "Midwest" "Midwest" "Midwest" ...
##  $ STATE   : chr  "WI" "WI" "WI" "WI" ...
##  $ HHID    : int  55616128 54704000 57874272 54106816 54569152 50199136 55660032 52425472 51796480 51796480 ...
##  $ FHOSP   : chr  "No" "No" "No" "No" ...
##  $ FDENT   : int  0 2 0 0 2 0 0 1 5 3 ...
##  $ FEMER   : int  0 0 1 0 0 1 1 5 5 4 ...
##  $ FDOCT   : int  0 0 0 1 0 1 3 1 0 0 ...
##  $ UIMMSTAT: chr  "US-born citizen" "US-born citizen" "US-born citizen" "US-born citizen" ...
##  $ U_USBORN: chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ UAGE    : int  22 30 33 41 34 39 19 18 24 21 ...
##  $ U_FTPT  : chr  "Full-time" "Full-time" "Part-time" "Part-time" ...
##  $ U_WKSLY : num  52 52 52 43 52 39 30 48 52 26 ...
##  $ U_HRSLY : int  40 40 30 40 40 45 20 32 40 40 ...
##  $ U_USHRS : int  40 40 30 25 40 30 40 40 40 47 ...
##  $ HEARNVAL: int  0 31468 24700 60000 55280 41333 105000 0 6000 42000 ...
##  $ HOTHVAL : int  0 5950 11340 39002 4200 8177 1000 44400 4800 1272 ...
##  $ HRETVAL : int  0 0 0 0 0 0 0 12000 0 0 ...
##  $ HSSVAL  : int  0 0 4920 0 0 5933 0 20400 0 0 ...
##  $ HWSVAL  : int  0 31468 24700 60000 55280 41333 105000 0 0 42000 ...
##  $ UBRACE  : chr  "White" "White" "White" "Black" ...
##  $ GENDER  : chr  "Female" "Female" "Male" "Female" ...
##  $ UEDUC3  : chr  "No HS diploma or GED" "HS diploma or GED, no bachelor's degree" "No HS diploma or GED" "No HS diploma or GED" ...
##  $ CEYES   : chr  "hazel" "blue" "brown" "brown" ...
##  $ CHAIR   : chr  "brown" "black" "brown" "black" ...

Dawniej wszystkie kolumny tekstowe były domyślnie konwertowane do factors. Aby tego uniknąć trzeba było użyć jawnie opcji stringsAsFactors = FALSE. Aktualnie jest włączona domyślnie na FALSE.

daneusa <- read.csv("dane/daneusa.csv",
                    stringsAsFactors = FALSE)

Inne warianty funkcji read.table() to np. read.delim() oraz read.delim2() do plików o stałej szerokości kolumn.



Dane można też importować poprzez “Import Dataset” w oknie środowiska.

“Przycisk do manualnego wczytania danych”
“Przycisk do manualnego wczytania danych”



readr

Jest to pakiet z Universum tidyverse (https://www.tidyverse.org/). Na stronie pakietu czytamy, że “the tidyverse is an opinionated collection of R packages designed for data science. All packages share an underlying design philosophy, grammar, and data structures.” Sprawdźmy jak to działa. Ważna informacja jest taka, że funkcje z rodziny tidyverse działają szybciej niż funkcje dostępne w default’owo dostępne w pakiecie utils.

# ?read_csv2
library(readr)

read_csv2(file = "dane/dane_titanic.csv", 
          n_max = 5) # inaczej niż w przypadku poznanej właśnie funkcji read.csv2()
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 5 Columns: 1
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (1): passenger_id,pclass,survived,name,sex,age,sibsp,parch,ticket,fare,c...
## 
## ℹ 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.
## # A tibble: 5 × 1
##   passenger_id,pclass,survived,name,sex,age,sibsp,parch,ticket,fare,cabin,emba…¹
##   <chr>                                                                         
## 1 "1,1,1,\"Allen, Miss. Elisabeth Walton\",1,29,0,0,24160,211.3375,B5,S,\"St Lo…
## 2 "2,1,1,\"Allison, Master. Hudson Trevor\",0,0.9167,1,2,113781,151.55,C22 C26,…
## 3 "3,1,0,\"Allison, Miss. Helen Loraine\",1,2,1,2,113781,151.55,C22 C26,S,\"Mon…
## 4 "4,1,0,\"Allison, Mr. Hudson Joshua Creighton\",0,30,1,2,113781,151.55,C22 C2…
## 5 "5,1,0,\"Allison, Mrs. Hudson J C (Bessie Waldo Daniels)\",1,25,1,2,113781,15…
## # ℹ abbreviated name:
## #   ¹​`passenger_id,pclass,survived,name,sex,age,sibsp,parch,ticket,fare,cabin,embarked,home.dest`
read_csv(file = "dane/dane_titanic.csv", 
         n_max = 5) # tu działa
## Rows: 5 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): name, cabin, embarked, home.dest
## dbl (9): passenger_id, pclass, survived, sex, age, sibsp, parch, ticket, fare
## 
## ℹ 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.
## # A tibble: 5 × 13
##   passenger_id pclass survived name    sex    age sibsp parch ticket  fare cabin
##          <dbl>  <dbl>    <dbl> <chr> <dbl>  <dbl> <dbl> <dbl>  <dbl> <dbl> <chr>
## 1            1      1        1 Alle…     1 29         0     0  24160  211. B5   
## 2            2      1        1 Alli…     0  0.917     1     2 113781  152. C22 …
## 3            3      1        0 Alli…     1  2         1     2 113781  152. C22 …
## 4            4      1        0 Alli…     0 30         1     2 113781  152. C22 …
## 5            5      1        0 Alli…     1 25         1     2 113781  152. C22 …
## # ℹ 2 more variables: embarked <chr>, home.dest <chr>
read_delim(file = "dane/dane_titanic.csv", 
           delim = ",", # -> działa po uzupełnieniu dodatkowego argumentu
           n_max = 5)
## Rows: 5 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): name, cabin, embarked, home.dest
## dbl (9): passenger_id, pclass, survived, sex, age, sibsp, parch, ticket, fare
## 
## ℹ 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.
## # A tibble: 5 × 13
##   passenger_id pclass survived name    sex    age sibsp parch ticket  fare cabin
##          <dbl>  <dbl>    <dbl> <chr> <dbl>  <dbl> <dbl> <dbl>  <dbl> <dbl> <chr>
## 1            1      1        1 Alle…     1 29         0     0  24160  211. B5   
## 2            2      1        1 Alli…     0  0.917     1     2 113781  152. C22 …
## 3            3      1        0 Alli…     1  2         1     2 113781  152. C22 …
## 4            4      1        0 Alli…     0 30         1     2 113781  152. C22 …
## 5            5      1        0 Alli…     1 25         1     2 113781  152. C22 …
## # ℹ 2 more variables: embarked <chr>, home.dest <chr>



Data.Table

Tak jak świat gitarzystów podzielony jest na sięgających po Fendery bądź GIBSONy, lub tak jak masy czytających komiksy o (przeważnie amerykańskich) superbohaterach na fanów DC bądź MARVEL’a, tak świat R’owców dzieli się na ludzi ze stajni tidyverse i tych używających Data.Table. Performance Data.Table jest niesamowity, jeśli chodzi o szybkość, jednak jest wielu konserwatystów odrzucających to rozwiązanie (sporo różnic w data wrangling’u)

# install.packages("data.table")
library(data.table)
fread(input = "dane/dane_titanic.csv", 
      nrows = 5)
##    passenger_id pclass survived                                            name
##           <int>  <int>    <int>                                          <char>
## 1:            1      1        1                   Allen, Miss. Elisabeth Walton
## 2:            2      1        1                  Allison, Master. Hudson Trevor
## 3:            3      1        0                    Allison, Miss. Helen Loraine
## 4:            4      1        0            Allison, Mr. Hudson Joshua Creighton
## 5:            5      1        0 Allison, Mrs. Hudson J C (Bessie Waldo Daniels)
##      sex     age sibsp parch ticket     fare   cabin embarked
##    <int>   <num> <int> <int>  <int>    <num>  <char>   <char>
## 1:     1 29.0000     0     0  24160 211.3375      B5        S
## 2:     0  0.9167     1     2 113781 151.5500 C22 C26        S
## 3:     1  2.0000     1     2 113781 151.5500 C22 C26        S
## 4:     0 30.0000     1     2 113781 151.5500 C22 C26        S
## 5:     1 25.0000     1     2 113781 151.5500 C22 C26        S
##                          home.dest
##                             <char>
## 1:                    St Louis, MO
## 2: Montreal, PQ / Chesterville, ON
## 3: Montreal, PQ / Chesterville, ON
## 4: Montreal, PQ / Chesterville, ON
## 5: Montreal, PQ / Chesterville, ON



Data.Table vs dplyr


Operacja / Warunek Zwycięzca Wydajności Szczegóły
Bardzo Duże Zbiory Danych data.table Osiąga przewagę 3-10x (a czasem więcej), głównie dzięki działaniu przez referencję i braku kopiowania całego zbioru.
Grupowanie i Agregacja
(by vs. group_by/summarise)
data.table Wykorzystuje algorytmy sortowania radix, co daje znaczną przewagę, zwłaszcza przy dużej liczbie grup.
Czytanie Danych
(fread vs. read_csv)
data.table Funkcja fread() jest uznawana za najszybszą metodę wczytywania plików CSV w R.
Mniejsze Zbiory Danych
(< 1 mln wierszy)
Remis / dplyr Różnice są minimalne lub dplyr może być nieznacznie szybszy w prostych operacjach ze względu na narzut data.table.


https://www.youtube.com/watch?v=SfrjF5YSj0Y



.RData

Ogromną zaletą formatu .RData jest fakt, że pozwala zapisywać w jednym pliku wiele obiektów, także jeśli nie są bazami danych. Kompresuje wielkość plików, przez co nie zajmują tyle samo miejsca, co pliki tekstowe bądź obiekty wczytane do R (w pamięci RAM). Możemy to sprawdzić w naszym systemie operacyjnym, zapisując ten sam obiekt w kilku formatach (skoro poznaliśmy jak dotąd co najmniej dwie opcje: .txt oraz .csv).

Do zapisu używamy funkcji save(), zaś do odczytu funkcji load()

save(mtcars, diamonds, iris, # dla przypomnienia - predefiniowane ramki
     file = 'dane/przyklad.RData')

Usuńmy trzy obiekty (mtcars, diamonds, iris), które potencjalnie mamy w Global Environment, żeby upewnić się co do prawidłowego działania funkcji load()

rm(mtcars, diamonds, iris)

I wczytajmy ponownie.

load('dane/przyklad.RData')

Są w środowisku? Spójrzmy w RStudio lub sprawdźmy kodem.

c("mtcars","iris") %in% ls()
## [1] TRUE TRUE



“Okienko po kliknięciu na dane w oknie eksploratora Windows”
“Okienko po kliknięciu na dane w oknie eksploratora Windows”



Sporą wadą plików .RData i używania poleceń save() i load() jest to, że przy wczytywaniu plików z dysku nadpisują one obiekty o takiej samej nazwie będące już w środowisku. Przykładowo, jeśli posiadamy już zbiór o nazwie diamonds, jego miejsce zajmie obiekt o tej samej nazwie, znajdujący się w pliku .Rdata.

Co więcej, w “internetach”, jak choćby na bardzo wiarygodnym i użytecznym forum stackoverflow można przeczytać, że pliki .Rdata mogą ulegać uszkodzeniu. Nie jest to nagminne, ale warto mieć w pamięci.


.rda

.rda to dokładnie ten sam format co .RData— tylko inna konwencja nazewnictwa. Niektórzy preferują .rda dla pojedynczych obiektów, a .RData dla zrzutów całej sesji, ale technicznie to identyczne pliki.

Właściwości techniczne

  • Format binarny (nieczytelny dla człowieka).

  • Kompresowany (domyślnie GZip, można zmienić np. na xz dla lepszej kompresji).

  • Można go przenosić między systemami (Windows, macOS, Linux).

  • Obsługuje dowolne typy obiektów R – nie tylko dane tabelaryczne.

  • Nie przechowuje środowiska globalnego jako całości (chyba że użyjesz save.image()).

save.image(file = "session.RData")



.Rds

To alternatywny dla .RData format plików. Również dobrze skompresowany, dający dodatkowo możliwość nazywania wczytanych obiektów. W tym formacie jednak, możemy zapisać tylko jeden plik.

# zapis
saveRDS(diamonds, 
        file = 'dane/diamonds.rds')
# wczyranie
diamonds <- readRDS('dane/diamonds.rds')
head(diamonds,3)
## # A tibble: 3 × 10
##   carat cut     color clarity depth table price     x     y     z
##   <dbl> <ord>   <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1  0.23 Ideal   E     SI2      61.5    55   326  3.95  3.98  2.43
## 2  0.21 Premium E     SI1      59.8    61   326  3.89  3.84  2.31
## 3  0.23 Good    E     VS1      56.9    65   327  4.05  4.07  2.31



Excel .xlsx

Pakietów do wczytywania Excel’owych plików jest wiele. Nauczmy się robić to używając pakietu np. readxl.

Instalacja i uruchomienie pakietów.

# install.packages("readxl")
# install.packages("writexl")
library(readxl)
library(writexl)

Obejrzyjmy zbiór poza RStudio.

A następnie wczytajmy dane.

# read_excel(path, sheet = NULL)
titanic1 <- read_excel(
  path = "dane/Titanic2.xlsx"
  ) # bez podania dodatkowych argumentów
## New names:
## • `` -> `...3`
## • `` -> `...4`
head(titanic1, 10)
## # A tibble: 10 × 4
##    `Sum of passenger_id` `Column Labels`   ...3 ...4       
##    <chr>                           <dbl>  <dbl> <chr>      
##  1 Row Labels                          0      1 Grand Total
##  2 0                              490200  91475 581675     
##  3 1                               20437   9703 30140      
##  4 2                               66779  11766 78545      
##  5 3                              402984  70006 472990     
##  6 1                              110284 165436 275720     
##  7 1                                 571  21615 22186      
##  8 2                                5428  44001 49429      
##  9 3                              104285  99820 204105     
## 10 Grand Total                    600484 256911 857395

Chcieliśmy inny sheet i raw data, zatem…

titanic2 <- read_excel(
  path = "dane/Titanic2.xlsx",
  sheet = 2 
  )
head(titanic2, 5)
## # A tibble: 5 × 15
##   passenger_id pclass survived name    sex    age sibsp parch ticket  fare cabin
##          <dbl>  <dbl>    <dbl> <chr> <dbl>  <dbl> <dbl> <dbl> <chr>  <dbl> <chr>
## 1            1      1        1 Alle…     1 29         0     0 24160   211. B5   
## 2            2      1        1 Alli…     0  0.917     1     2 113781  152. C22 …
## 3            3      1        0 Alli…     1  2         1     2 113781  152. C22 …
## 4            4      1        0 Alli…     0 30         1     2 113781  152. C22 …
## 5            5      1        0 Alli…     1 25         1     2 113781  152. C22 …
## # ℹ 4 more variables: embarked <chr>, boat <chr>, body <dbl>, home.dest <chr>

A co jeśli mamy taki plik? Obejrzyjmy go w Excelu.

Wówczas

titanic3 <- read_excel(
  path = "dane/Titanic3.xlsx",
  sheet = 2, skip = 3, col_names = F
  )
## New names:
## • `` -> `...1`
## • `` -> `...2`
## • `` -> `...3`
## • `` -> `...4`
## • `` -> `...5`
## • `` -> `...6`
## • `` -> `...7`
## • `` -> `...8`
## • `` -> `...9`
## • `` -> `...10`
## • `` -> `...11`
## • `` -> `...12`
## • `` -> `...13`
## • `` -> `...14`
## • `` -> `...15`
head(titanic3, 2)
## # A tibble: 2 × 15
##    ...1  ...2  ...3 ...4   ...5   ...6  ...7  ...8 ...9  ...10 ...11 ...12 ...13
##   <dbl> <dbl> <dbl> <chr> <dbl>  <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr> <chr>
## 1     1     1     1 Alle…     1 29         0     0 24160  211. B5    S     2    
## 2     2     1     1 Alli…     0  0.917     1     2 1137…  152. C22 … S     11   
## # ℹ 2 more variables: ...14 <dbl>, ...15 <chr>

Niestety bez nagłówków kolumn. Czasem gdy cyklicznie otrzymujemy od kogoś zrzuty w Excel’u, teoretycznie o tej samej strukturze, ale wycięte przez przypadek przez użytkownika, możemy nagłówki zaczerpnąć z poprzedniej wersji zbioru.

names(titanic3) <- names(titanic2) # ale tu mieliśmy szczęśliwie skąd pożyczyć

head(titanic3, 3)
## # A tibble: 3 × 15
##   passenger_id pclass survived name    sex    age sibsp parch ticket  fare cabin
##          <dbl>  <dbl>    <dbl> <chr> <dbl>  <dbl> <dbl> <dbl> <chr>  <dbl> <chr>
## 1            1      1        1 Alle…     1 29         0     0 24160   211. B5   
## 2            2      1        1 Alli…     0  0.917     1     2 113781  152. C22 …
## 3            3      1        0 Alli…     1  2         1     2 113781  152. C22 …
## # ℹ 4 more variables: embarked <chr>, boat <chr>, body <dbl>, home.dest <chr>



SPSS (.sav)


Należy pamiętać jak wygląda praca w programie SPSS. Mamy tam dwa okna, pierwszy widok umożliwia podejrzenie danych, drugi pozwala przyjrzeć się kategoriom, jeśli zmienna ma taki charakter (factor w R)

“Widok SPSS’a”

Instalacja i uruchomienie pakietów.

# install.packages("haven")
require(haven)
## Loading required package: haven

I wczytanie danych.

spss_df <- read_sav(file = "dane/IBM SPSS Sample Files/accidents.sav")

# jak podejrzeć nazwy kategorii?
# attr(spss_df$gender, "label")
attr(spss_df$gender, "labels")
##   Male Female 
##      0      1
class(spss_df)
## [1] "tbl_df"     "tbl"        "data.frame"
typeof(spss_df)
## [1] "list"
# so...
is.data.frame(spss_df) # how?
## [1] TRUE
summary(spss_df)
##      agecat         gender        accid            pop        
##  Min.   :1.00   Min.   :0.0   Min.   :54123   Min.   :187791  
##  1st Qu.:1.25   1st Qu.:0.0   1st Qu.:57334   1st Qu.:196416  
##  Median :2.00   Median :0.5   Median :60967   Median :199633  
##  Mean   :2.00   Mean   :0.5   Mean   :60801   Mean   :199035  
##  3rd Qu.:2.75   3rd Qu.:1.0   3rd Qu.:64610   3rd Qu.:202586  
##  Max.   :3.00   Max.   :1.0   Max.   :66804   Max.   :208239


Inny sposób (z użyciem innego pakietu), który być może jest wygodniejszy do importu danych ankietowych (głównie kategorialne zmienne)

# install.packages("foreign")
library(foreign)
spss_df2 <- read.spss(file = "dane/IBM SPSS Sample Files/accidents.sav",
                     use.value.labels = TRUE # ten argument pozwala korzystać z etykiet
                     )

class(spss_df2)
## [1] "list"
typeof(spss_df2)
## [1] "list"
is.data.frame(spss_df2)
## [1] FALSE
summary(spss_df2)
##        Length Class  Mode   
## agecat 6      factor numeric
## gender 6      factor numeric
## accid  6      -none- numeric
## pop    6      -none- numeric



Internet

Znając link do strony, gdzie ktoś trzyma interesujący nas zasób bazodanowy, możemy posłużyć się funkcjami dostępnymi w R, żeby taką ramkę ściągnąć i zacząć “obrabiać” bezpośrednio w środowisku R

(investment_annual_summary <- readr::read_csv("https://assets.datacamp.com/production/repositories/5756/datasets/d0251f26117bbcf0ea96ac276555b9003f4f7372/investment_annual_summary.csv", show_col_types = FALSE))
## # A tibble: 42 × 3
##    fiscal_year region                          dollars_in_millions
##          <dbl> <chr>                                         <dbl>
##  1        2012 East Asia and the Pacific                      2548
##  2        2012 Europe and Central Asia                        2915
##  3        2012 Latin America and the Caribbean                3680
##  4        2012 Middle East and North Africa                   2210
##  5        2012 South Asia                                     1312
##  6        2012 Sub-Saharan Africa                             2733
##  7        2013 East Asia and the Pacific                      2873
##  8        2013 Europe and Central Asia                        3261
##  9        2013 Latin America and the Caribbean                4822
## 10        2013 Middle East and North Africa                   2038
## # ℹ 32 more rows


# przykład z internetowego tutorial'u Dr Eugene O'Loughlin'a
url = "https://raw.githubusercontent.com/eoloughlin/How-To-R/master/24_Data_File.csv"
priceData <- read.csv(url)


head(priceData, 6) # Zobacz sześć pierwszych wierszy
##   Oil Gold
## 1  50 1267
## 2  46 1238
## 3  54 1157
## 4  55 1192
## 5  55 1234
## 6  52 1231


tail(priceData, 6) # Zobacz sześć ostatnich wierszy
##    Oil Gold
## 7   53 1267
## 8   51 1246
## 9   47 1260
## 10  49 1237
## 11  51 1283
## 12  55 1314


names(priceData) # sprawdź nazwy kolumn
## [1] "Oil"  "Gold"




Zewnętrzne bazy danych

Przykład połączenia się z portalem https://clinicaltrials.gov/ . Jest to publiczne źródło informacji o badaniach klinicznych nad lekami (po zarejestrowaniu się). Korzystając z pakietu RPostgreSQL możemy kwerendować bazę portalu używając składni SQL (w implementacji PostgreSQL)

###### Packages ###### 

# install.packages("Rtools")
# install.packages("RPostgreSQL")
# install.packages("DBI")
library(RPostgreSQL)

###### Credentials ###### 
# https://aact.ctti-clinicaltrials.org/r
Hostname        = "aact-db.ctti-clinicaltrials.org"
Port            =  5432
Database_name   = "aact"
User_name       = "LooserName"
Password        = "password"

###### Connection ###### 
drv <- dbDriver('PostgreSQL')
class(drv)

con <- dbConnect(drv,
                 dbname = Database_name,
                 host="aact-db.ctti-clinicaltrials.org",
                 port= Port ,
                 user=(User_name),
                 password=Password)
class(con)

###### Info ###### 
# https://aact.ctti-clinicaltrials.org/schema
# https://aact.ctti-clinicaltrials.org/data_dictionary

###### Query ###### 
studyTypes <- dbGetQuery(con,
                          "SELECT DISTINCT study_type FROM studies")

suties <- dbGetQuery(con,
                          "SELECT * FROM studies LIMIT 20")



############### libraries ###############
library(DBI)
library(odbc)
library(data.table)

############### Nokia ###############
con <- dbConnect(odbc(), 
                 Driver = "SQL Server",
                 Server = "nazwa_serwera", 
                 UID = "Uzytkownik_readonly",
                 PWD = rstudioapi::askForPassword("Uzytkownik_readonly@2"))


############### queries ###############

query <- c("SELECT Top 10 * FROM CT.dbo.facilities f")

studies <- data.table(
  dbGetQuery(con, query)
  )

###
query <- c(
"SELECT f.nct_id AS project_id, f.country, COUNT(f.id) AS sites_count
FROM CT.dbo.facilities f
    JOIN (SELECT DISTINCT st.nct_id 
            FROM CT.dbo.studies st
            LEFT JOIN CT.dbo.sponsors sp ON sp.nct_id = st.nct_id
            LEFT JOIN CT.dbo.calculated_values cv ON st.nct_id = cv.nct_id
            LEFT JOIN CT.dbo.conditions cn ON st.nct_id = cn.nct_id
            LEFT JOIN CT.dbo.eligibilities e ON st.nct_id = e.nct_id
            WHERE
                st.start_date > '2010-01-01' AND st.study_type = 'Interventional'
                AND sp.agency_class = 'INDUSTRY' AND sp.lead_or_collaborator = 'lead'
            ) s ON f.nct_id = s.nct_id
WHERE 
    f.country IS NOT NULL 
  AND f.country IN ('Poland', 'Austria','Belgium','Bosnia','Denmark','Estonia','Finland','Latvia',
                              'Lithuania','Macedonia','Netherlands','Norway')
GROUP BY 
    f.nct_id, f.country;"
)

SiteCount <- data.table(
  dbGetQuery(con, 
             query)
  )




Wczytanie i zapis wielu plików

Wyobraźmy sobie sytuację, że nie mamy licencji do SPSS’a, a znalezione pliki są zapisane w formacie .sav. Jeśli chcemy skorzystać z tym danych mimo wszystko, to możemy je w R skonwertować do każdego innego formatu. Poniżej zajawka jak to zrobić stojąc przed koniecznością skonwertowania wielu plików.

# install.packages("tidyverse")
# install.packages("fs")
library(tidyverse)
library(fs)

# wczytywanie wielu plików na raz (np. SPSS'owych)

lista_plikow <- dir("dane/IBM SPSS Sample Files/")

dane_spss_mult <- list()

library(haven)

for (i in seq_along(lista_plikow)) { # == 1:length(lista_plikow)
  dane_spss_mult[[i]] <- read_sav(
    file = paste0("dane/IBM SPSS Sample Files/",
                  lista_plikow[[i]]
                  )
    )
  }

library(tidyverse)

dane_spss_mult <- set_names(x = dane_spss_mult,
                            nm = lista_plikow)

# sprawdzenie losowego zbioru
head(dane_spss_mult$bankloan.sav, 4)


# potencjalnie mogę sobie wyciąg  z listy zbiory, które mnie interesują i przypisywać do obiektów
accidents.sav <- dane_spss_mult$accidents.sav
class(accidents.sav)

adl.sav <- dane_spss_mult$adl.sav
advert.sav <- dane_spss_mult$advert.sav
bankloan.sav <- dane_spss_mult$bankloan.sav
behavior.sav <- dane_spss_mult$behavior.sav
car_sales.sav <- dane_spss_mult$car_sales.sav
contacts.sav <- dane_spss_mult$contacts.sav
customer_dbase.sav <- dane_spss_mult$customer_dbase.sav
demo.sav <- dane_spss_mult$demo.sav
dietstudy.sav <- dane_spss_mult$dietstudy.sav
dmdata3.sav <- dane_spss_mult$dmdata3.sav
ozone.sav <- dane_spss_mult$ozone.sav
poll_cs_sample.sav <- dane_spss_mult$poll_cs_sample.sav
satisf.sav <- dane_spss_mult$satisf.sav
telco.sav <- dane_spss_mult$telco.sav
workprog.sav <- dane_spss_mult$workprog.sav

getwd() # sprawdzenie ścieżki

# zapisywanie wielu plików na raz (np. do .csv)
data_names <- names(dane_spss_mult)
for(i in 1:length(data_names)) {
  write.csv2(x = get(data_names[i]),
             file =  paste0("/dane/IBM SPSS Sample Files/",
                            data_names[i],
                            ".csv"),
             row.names = FALSE)
  }




Zarządzanie plikami i folderami z poziomu R

dir()         # pliki i foldery w ścieżce roboczej

list.files()  # lista plików i folderów

list.dirs()   # lista potencjalnych ścieżek dostępu

dir.create('~/Statystyka1_R/materialy/Zaj_3/dane/Dane2')  # stworzenie folderu

dir.exists('dane')  # sprawdzenie czy folder istnieje

file.copy(from = './script.R', 
          to = 'Zaj_3') # skopiowanie pliku

file.create('dane/script_new.R') # stworzenie pliku

file.edit('dane/script_new.R')   # edycja pliku

file.exists('dane/script_new.R') # sprawdzanie czy plik istnieje

file.remove('dane/script.R') # skasowanie pliku

file.rename('dane/script.R', 'dane/script2.R') # zmiana nazwy pliku

file.size('dane/script.R')   # wielkość pliku

file.info('dane/script.R') # info o pliku


Przy zarządzaniu plikami, warto jeszcze zdawać sobie sprawę, że istnieje możliwość zdalnego pakowania i rozpakowywania plików, przez polecenie unzip

unzip(zipfile = '~/Statystyka1_R/materialy/Zaj_3/dane/ibm_spss_sample_files_0.zip',
      exdir = '~/Statystyka1_R/materialy/Zaj_3/dane/Dane2')




Czas to pieniądz


Porównanie szybkość trzech funkcji do wczytywania plików z danymi

# install.packages("microbenchmark")
library(microbenchmark)

compare <- microbenchmark(read.csv2("dane/diamonds2.csv"), 
                          readRDS("dane/diamonds2.rds"),
                          load("dane/diamonds2.rda"),
                          times = 10)

compare
## Unit: milliseconds
##                             expr        min         lq      mean     median
##  read.csv2("dane/diamonds2.csv") 123.067801 137.034101 182.25557 172.985051
##    readRDS("dane/diamonds2.rds")   8.019701   8.591401  14.60872   9.678601
##       load("dane/diamonds2.rda")   8.498001   9.513301  14.06737   9.862251
##        uq      max neval
##  231.1824 258.1293    10
##   16.2806  42.2696    10
##   11.9462  44.0658    10
library(knitr)
kable(compare)
expr time
readRDS(“dane/diamonds2.rds”) 42269601
load(“dane/diamonds2.rda”) 44065801
read.csv2(“dane/diamonds2.csv”) 223434901
read.csv2(“dane/diamonds2.csv”) 180148601
read.csv2(“dane/diamonds2.csv”) 231182401
read.csv2(“dane/diamonds2.csv”) 258129301
readRDS(“dane/diamonds2.rds”) 8591401
load(“dane/diamonds2.rda”) 9513301
load(“dane/diamonds2.rda”) 9742401
readRDS(“dane/diamonds2.rds”) 9296701
read.csv2(“dane/diamonds2.csv”) 137034101
readRDS(“dane/diamonds2.rds”) 18685401
readRDS(“dane/diamonds2.rds”) 9457302
read.csv2(“dane/diamonds2.csv”) 231940701
read.csv2(“dane/diamonds2.csv”) 165821501
read.csv2(“dane/diamonds2.csv”) 143155001
load(“dane/diamonds2.rda”) 11946200
load(“dane/diamonds2.rda”) 10644201
readRDS(“dane/diamonds2.rds”) 8220901
load(“dane/diamonds2.rda”) 8784901
readRDS(“dane/diamonds2.rds”) 16280601
read.csv2(“dane/diamonds2.csv”) 123067801
read.csv2(“dane/diamonds2.csv”) 128641402
readRDS(“dane/diamonds2.rds”) 15365701
readRDS(“dane/diamonds2.rds”) 8019701
readRDS(“dane/diamonds2.rds”) 9899901
load(“dane/diamonds2.rda”) 8498001
load(“dane/diamonds2.rda”) 17754401
load(“dane/diamonds2.rda”) 9911402
load(“dane/diamonds2.rda”) 9813101
# ciekawostka
df <- data.frame(col1 = seq(1,10000, by = 1), 
                 col2 = rep(x = 1:1000, 10), 
                 col3 = rnorm(10000))

m <- as.matrix(df)

microbenchmark(df[,1], m[,1], times = 100)
## Unit: microseconds
##     expr    min      lq     mean  median      uq    max neval
##  df[, 1]  3.801  4.4515  8.69795  6.0510 10.7005 66.900   100
##   m[, 1] 13.300 16.0010 26.54312 19.1005 32.7010 88.701   100
microbenchmark(df[1,], m[1,], times = 100)
## Unit: nanoseconds
##     expr   min    lq     mean  median    uq    max neval
##  df[1, ] 21200 24701 30979.90 28901.5 32151 156100   100
##   m[1, ]   400   602  1123.06   800.0  1000  14302   100




# install.packages("profvis")
library(profvis)

profvis({

  #create dataset
data <- data.frame(y=c(6, 7, 7, 9, 12, 13, 13, 15, 16, 19, 22, 23, 23, 25, 26),
                   x=c(1, 2, 2, 3, 4, 4, 5, 6, 6, 8, 9, 9, 11, 12, 12))

# Tworzy ramkę danych data z dwiema kolumnami:
# y (wartości zmiennej zależnej)
# x (wartości zmiennej niezależnej)
model <- lm(y~x, data=data)
summary(model)
  

library(ggplot2)

ggplot(data,aes(x, y)) +
  geom_point() + # Wykres  punktowy geom_point() 
  geom_smooth(method='lm') # wraz z dopasowaną linią regresji 

}) # koniec Profilowania

Cały blok kodu jest profilowany za pomocą funkcji profvis(). Profilowanie pozwala analizować, ile czasu zajmują poszczególne etapy wykonywania kodu (np. tworzenie danych, dopasowanie modelu, generowanie wykresu).

Innymi słowy kod tworzy prosty model regresji liniowej, wizualizuje go za pomocą wykresu punktowego z linią regresji, a następnie funkcja profvis() z pakietu {profvis} analizuje jego wydajność.


Sprawdzanie zasobów własnej maszyny w konsoli R

# install.packages("benchmarkme")
library(benchmarkme)
get_cpu()
## $vendor_id
## [1] "GenuineIntel"
## 
## $model_name
## [1] "11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz"
## 
## $no_of_cores
## [1] 8


# install.packages("parallel")
library(parallel)
detectCores() # == get_cpu()$no_of_cores
## [1] 8



Źródła i inspiracje pomocne w przygotowaniu niniejszej prezentacji: