##%######################################################%##
#                                                          #
####            Datové objekty a import dat             ####
#                                                          #
##%######################################################%##

# Balíčky -----------------------------------------------------------------
library(tidyverse)
library(readxl)
library(haven)

# Datové objekty ----------------------------------------------------------

# * Listy -------------------
# Lists are a step up in complexity from atomic vectors, because lists can 
# contain other lists. This makes them suitable for representing hierarchical 
# or tree-like structures. 
x <- list(1:20, c(TRUE, FALSE, TRUE), letters)
x

# A very useful tool for working with lists is str() because it focusses on 
# the structure, not the contents.
str(x)

x_named <- list(nums = 1:20, 
                binary = c(TRUE, FALSE, TRUE),
                alphabet = letters)
str(x_named)

# Unlike atomic vectors, list() can contain a mix of objects
y <- list("a", 1L, 1.5, TRUE)
str(y)

# Lists can even contain other lists!
z <- list(list(1, 2), list(3, 4))
str(z)

# ** Subsetting listu --------------
# There are three ways to subset a list, 
# which I’ll illustrate with a list named a:
a <- list(
  int_vec = 1:3, 
  str_vec = c("This", "is", "a", "string"), 
  dbl_vec = pi, 
  list_vec = list(-1, -5)
  ) 

str(a)

# [ extracts a sub-list. The result will always be a list.
a[1:2]
typeof(a[1:2])

a[c(2, 3)]

# [[ extracts a single component from a list. 
# It removes a level of hierarchy from the list.
a[[1]]
typeof(a[[1]])

# What does this do?
a[[c(2, 1)]]
a[[2]][[1]]
a[[2]][c(3,4)]

# $ is a shorthand for extracting named elements of a list. 
# It works similarly to [[ except that you don’t need to use quotes.
a$str_vec
a[["str_vec"]]

# [ extracts a sub-list. The result will always be a list.
str(a[1:2])

# * Faktory -----------------------
# Factors are designed to represent categorical data that can take a fixed set 
# of possible values. Factors are built on top of integers, 
# and have a levels attribute:
temps <- c("cold", "freezing",  "hot", "warm", 
           "cold", "cold", "warm", "freezing")
temps
typeof(temps)

temps_fct <- factor(temps)
typeof(temps_fct)
temps

attributes(temps_fct)
levels(temps_fct)

unclass(temps_fct)

# Defaultní je pořadí úrovní podle abecedy
temps_fct <- factor(temps, levels = c("freezing", "cold", "warm", "hot"))
temps_fct

# Často jsou jednotlivé kategorie nejprve kódovány numericky
temps <- c(2, 1, 4, 3, 2, 2, 3, 1)
temps
temps_fct <- factor(temps,
                    levels = c(1, 2, 3, 4),
                    labels = c("freezing", "cold", "warm", "hot"))
temps_fct
unclass(temps_fct)


# * Procvičování práce s vektory ----------------
# Počet cursing words v několika Tarantinových filmech

# Vektor s názvy filmů
movies <- c("Django Unchained", "Inglorious Basterds", "Jackie Brown",
            "Kill Bill: Vol. 1", "Kill Bill: Vol. 2", "Pulp Fiction", 
            "Reservoir Dogs")

# Vektor s početem "cursing words"
profanities <- c(262, 58, 368, 57, 69, 469, 421)
names(profanities) <- movies # pojmenování jeho prvků



# ** Výběr prvků --------------------------------------------------
profanities

# Vymyslete co nejvíce způsobů jak vybrat prvky s počtem cursing words 
# pro oba díly Kill Bill, které jsou v pořadí na 4 a 5 místě 



# ** Součet vektorů --------------------------------------------------------

# Kolikrát v uvedených filmech zaznělo slovo "hell" nebo "goddamn"
hell <-  c(10, 4, 10, 3, 1, 2, 12)
goddamn <-  c(28, 8, 27, 7, 5, 28, 10)
names(hell) <- movies
names(goddamn) <- movies
hell
goddamn


# Vytvořte dva nové vektory, první bude udávat, kolikrát v jednotlivých
# filmech zaznělo slovo "hell" + "goddamn",
# druhý celkový součet "hell" + "goddamn"


# ** Logické operátory -------------------------------------------------------
  # < for less than
  # > for greater than
  # <= for less than or equal to
  # >= for greater than or equal to
  # == for equal to each other
  # != not equal to each other

# Ve kterých filmech zaznělo více než 100 cursing words?
# subsetujte vektor movies, aby zůstaly pouze filmy, pro které platí
# tato podmínka


# Zaznívalo ve filmech více slovo "hell", nebo "goddamn"?
# Vytvořte logický vektor, který má hodnoty TRUE, pokud ve filmu zaznělo častěji
# slovo goddam, jinak FALSE


# Uplatněte na tento vektor funkci sum

# A nakonec pomocí tohoto vektoru subsetujte vektor movies,
# aby zůstaly pouze filmy, ve kterých častěji zaznělo slovo "hell"
# Pozor, je nutné uplatnit negaci pomocí !


# * Matice (matrix) -----------------------
# In R, a matrix is
 # a collection of elements of the SAME DATA TYPE (numeric, character, or logical)
 # arranged into a fixed number of rows and columns.
 # a matrix is therefore twodimensional.

x <- seq(from = 1, to = 12)
x

# sekvence čísel od 1 do 12
x <- 1:12
x

# První argumentem je vždy atomický vektor,
# argument byrow určuje, jestli se má matice plnit po řádcích,
# argument nrow nebo ncol určuje počet řádků, resp. sloupců matice
matrix(x, byrow = TRUE, nrow = 3)
matrix(x, byrow = FALSE, nrow = 3)
matrix(x, byrow = FALSE, ncol = 2)


# Základem pro tvorbu matice budou dva vektory
# První už máme - počet cursing words v Tarantinových filmech
profanities

# Přidáme ještě počet úmrtí
deaths <- c(47, 48, 4, 63, 11, 7, 10)
names(deaths) <- movies
deaths

# Sloučíme jejich hodnoty do jednoho vektoru
profanities_deaths <- c(profanities, deaths)
profanities_deaths

# Přichystáme si názvy pro sloupce matice
columns <- c("Profanities", "Deaths")

# Konečně vytvoříme matici
m <- matrix(
  profanities_deaths, # Těmito hodnotami se bude plnit
  byrow = FALSE, # byrow = FALSE, tedy hodnotu se budou plnit po sloupcích
  ncol = 2, # máme vlastně dvě proměnné, proto dva sloupce
  dimnames = list( # nastavíme si i jména řádků a slpupců matice
    movies, # Labely pro řádky matice
    columns # Labely pro sloupce matice
  )
)

m

View(m)

# Použijte funkce colSums(), colMeans(), rowSums() a rowMeans() na matici m
# Co dělají tyto funkce?





# Přidání sloupce s rokem uvedení filmu
# Nejprve vytvoříme příslušný vektor
Year <- c(2012, 2009, 1997, 2003, 2004, 1994, 1992) 

# poté použijeme funkci cbind (bind columns)
m <- cbind(m, Year) 
m

# Přidání řádků
# Nejprve vytvoříme nový vektor
# kvůli nestandardnímu názvu musíme použít backticks (zpětný apostrof)
`The Hateful Eight` <- c(107, 20, 2015)

# poté použijeme funkci rbind (bind columns)
m <- rbind(m, `The Hateful Eight`) 
m

# Výběr prvků z matice
  # Similar to vectors, you can use the square brackets [ ] to select one or 
  # multiple elements from a matrix.
  # Whereas vectors have one dimension, matrices have two dimensions. You should
  # therefore use a comma to separate that what to select from the rows from that what
  # you want to select from the columns.

# Pomocí číselných indexů/vektorů
m[8, ] # celý osmý řádek
m[8, 3] #  osmý řádek, třetí sloupec
m[ , 2] # všechny řádky, druhý sloupce

# Pomocí názvů řádků/sloupců (pokud má matice nastavené rownames/colnames)
m["Pulp Fiction", "Profanities"]

# Pomocí logického vektoru
after_2000 <- m[, "Year"] > 2000
m[after_2000, ]

# Jaký byl průměrný počet mrtvých ve uvedených filmech?
# Vyberte z matice sloupec "Deaths" a použijte na něj funkci mean()



# Jaký je Tarantino index (tj. počet mrtvých na počet nadávek) 
# pro Inglorious Basterds?
# Vyberte z matice příslušné prvky 
  # počet mrtvých pro Inglorious Basterds
  # počet nadávek v Inglorious Basterds
# a vydělte je

m["Inglorious Basterds", "deaths"] / m["Inglorious Basterds", "profanities"]

# * Data frames -----------------------
# Data Frame je matice tak, jak ji obvykle chápeme při analýze dat
# A data frame has the variables of a data set as columns and the
# observations as rows
# Na rozdíl od matrix může obsahovat různé typy vektorů

# Vyvolání Data Frame z R
data() # přehled datasetů z nainstalovaných balíčků
data(USArrests) # zpřístupnění datasetu R, aby o něm "vědělo"
View(USArrests) # jakákoli další funkce na něj uplatněná pak dataset uloží
                # do globálního prostředí

?USArrests # i k datasetům je většinou nápověda

# Jak se zorientovat v Data Frame?
 # head()
 # tail()
 # str() nebo glimpse()
 # summary()
# Podívejte se do popisu těchto funkcí v jejich nápovědě.
# Co dělají tyto funkce?
# Použijte je na dataset USArrests
# U funkcí head() a tail() si ještě zkuste pohrát s argumentem n






# Tvorba dataframe přímo v R
planets <- data.frame(
  name = c("Mercury", "Venus", "Earth", "Mars", 
           "Jupiter", "Saturn", "Uranus", "Neptune"),
  type = c("Terrestrial", "Terrestrial", "Terrestrial","Terrestrial", 
           "Gas giant", "Gas giant", "Gas giant", "Gas giant"),
  diameter = c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883),
  rotation = c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67),
  rings = c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)
)

planets

# Výběr prvků
# První až třetí řádek, první sloupec
planets[1:3, 1]

# První a třetí sloupec
planets[c(1, 3)]

# První až třet řádek, slopec "name"
planets[1:3,"name"]

# slopec "name"
planets$name
planets["name"]

# Řazení
planets$diameter
order(planets$diameter) # funkce order určí pořadí hodnot, defaultně od nejmenší po největší
# výsledkem je numerický vektor s pozicemi prvků podle jejich velikosti
# nejmenší průměr má tedy planeta 1 (Merkur), druhý nejmenší planeta 4 (Merkur) atd.

# argument descresing = TRUE změní způsob řazení - od největšího po nejmenší
order(planets$diameter, decreasing = TRUE) 

# Výsledným vektorem pak lze subsetovat dataframe planets
planets[order(planets$diameter, decreasing = FALSE), ]
planets[order(planets$diameter, decreasing = TRUE), ]

# funkce sort seřadí hodnoty
# výsledkem je původní vektor hodnot, ale sařazený
sort(planets$diameter)
sort(planets$diameter, decreasing = TRUE)

# Filtrování
planets[planets$rotation < 0, ]
subset(planets, rotation < 0)
subset(planets, rotation < 0 & rings == TRUE)

# * Tibbles -----------------------------------------------------------------

# Tibbles are data frames, but they tweak some older behaviours 
# to make life a little easier

# Most other R packages use regular data frames, so you might want to coerce 
# a data frame to a tibble. You can do that with as_tibble():

iris # u obyčejného dataframu se může stát, že vám zahltí konzoli

as_tibble(iris) # v případě tibble nikoli
# navíc hned vidíte informace o typu proměnných
# a počet řádků a sloupců

# You can create a new tibble from individual vectors with tibble(). 
# tibble() will automatically recycle inputs of length 1, 
# and allows you to refer to variables that you just created, as shown below.
tibble(
  v1 = 1:5, 
  v2 = 1, # pokud má vektor délku == 1, je "recyklován"
  v3 = v1 ^ 2 + v2 # tohle by v obyčejném dataframu nešlo, 
) # odkazovat se na vektory, které nejsou vytvořeny v global environment

data.frame(
  v1 = 1:5, 
  v2 = 1, 
  v3 = v1 ^ 2 + v2 # Error, pokud vektory v1 a v2 nejsou v global environment, 
) 




# Another way to create a tibble is with tribble(), short for transposed tibble. 
# tribble() is customised for data entry in code: column headings are defined 
# by formulas (i.e. they start with ~), and entries are separated by commas

# Na české klávesnici napíšete vlnovku RAlt + 1 = ~
tribble( # pomocí funkce tribble můžete tibble vytvářet po řádcích
  ~x, ~y, ~z, # názvy sloupců
  
  "a", 2, 3.6, # hodnoty
  "b", 1, 8.5
)


# Tibbles have a refined print method that shows only the first 10 rows, 
# and all the columns that fit on screen. This makes it much easier to work 
# with large data. In addition to its name, each column reports its type
tibble(
  a = Sys.time() + runif(1e3) * 86400,
  b = as.Date(Sys.time()) + runif(1e3) * 30,
  c = 1:1e3,
  d = runif(1e3),
  e = sample(letters, 1e3, replace = TRUE)
)

# So far all the tools you’ve learned have worked with complete data frames. 
# If you want to pull out a single variable, you need some new tools, $ and [[. 
# [[ can extract by name or position; $ only extracts by name but is a little less typing.

df <- tibble(
  x = runif(5),
  y = rnorm(5),
  z = rlnorm(5)
)
df




# Extract by name
df$x # returns atomic vector
df[["x"]] # returns atomic vector

df["x"] # returns tibble

df[c("x", "y")] # multiple columns


# Extract by position
df[[1]]
df[1]



# Exercises
# How can you tell if an object is a tibble? (Hint: try printing mtcars, 
# which is a regular data frame).
# What is the appropriate test function?
mtcars

# Compare and contrast the following operations on a data.frame and equivalent 
# tibble. What is different? Why might the default data frame behaviours cause 
# you frustration?
my_df <- data.frame(
  abc = c(1, 2, 3), 
  efg = c("a", "b", "c")
)

my_tibble <- as_tibble(my_df)

my_df$a
my_tibble$a

my_df$abc
my_tibble$abc

my_df[, "efg"]
my_tibble[, "efg"]

my_df[["abc"]]
my_tibble[["abc"]]

# Import dat ----------------------------

# * Import flat files ---------------------------------------
# flat files jsou jednoduché databázové soubory 
# uložené ve formě prostého textu

# Zkuste si nejdříve soubory swimming_pools.csv, hotdogs_1.txt
# a hotdogs_2.txt otevřít v notepadu nebo jiném jednoduchém textovém editoru

### Import swimming_pools.csv:

# funkce read_csv se používá, pokud jsou hodnoty oddělené čárkou,
# a desetinná místa tečkou

pools <- read_csv("data/swimming_pools.csv")
glimpse(pools)

# funkce read_csv (ale i ostatní funkce z readr) má mnoho dalších argumentů
# např. si můžeme manuálně specifikovat typy sloupců

pools <- read_csv(
  "data/swimming_pools.csv",
  col_types = "cccifccc"
)

# c = character
# i = integer
# n = number
# d = double
# l = logical
# f = factor
# D = date
# T = date time
# t = time
# ? = guess
# _ or - = skip

# Dále můžeme argumentem name_repair "opravit" nestandardní názvy proměnných
pools <- read_csv(
  "data/swimming_pools.csv",
  col_types = "cccifccc",
  name_repair = "universal"
)
glimpse(pools)

# Nebo specifikovat názvy proměnných (sloupců) ručně
pools <- read_csv(
  "data/swimming_pools.csv",
  col_types = "cccifccc",
  skip = 1,
  col_names = c("name", "address", "suburb", "postcode", "state",
                "business_cat", "lga", "region")
)
glimpse(pools)

# Pokud jsou hodnoty oddělené tabulátory, můžeme použít 
hotdogs_1 <- read_tsv("data/hotdogs_1.txt")
hotdogs_1

hotdogs_1 <- read_tsv("data/hotdogs_1.txt", 
                      col_types = "fii") # Opět můžeme změnit typ sloupců
hotdogs_1

# Co je špatně při tomto importu dat? Zkuste to napravit 
# TIP: bude k tomu potřebovat argument col_names
hotdogs_2 <- read_tsv("data/hotdogs_2.txt")
hotdogs_2
glimpse(hotdogs_2)



# Pomocí funkcí slice_min a slice_max můžete vybrat určitý počet pozorování
# s nejmenšími nebo největšími hodnotami zvolené proměnné

# Select the hot dog with the least calories using slice_min()
slice_min(hotdogs_2, calories, n = 10)

# Select the observation with the most sodium using slice_max()
slice_max(hotdogs_2, sodium, n = 10)

# Nejobecnější je funkce read_delim, kde si můžete sami specifikovat oddělovač
# hodnot argumentem delim
read_delim("data/swimming_pools.csv", delim = ",")
read_delim("data/hotdogs_1.txt", delim = "\t")

# Argumentem na také můžete změnit, jaké hodnoty se mají považovat za chybějící
# defaultně na = c("", "NA"), čili prázdné buňky a písmena NA
read_delim("data/hotdogs_1.txt", delim = "\t", na = c("186", "495"))


# * Import dat z Excelu ----------------------------

# Dva základní příkazy:
?excel_sheets() # Výčet sheets v daném excelovském (.xls, .xlsx) souboru
?read_excel() # Načtení souboru excelovského formátu

excel_sheets("data/latitude.xlsx")

# Read the first sheet of latitude.xlsx:
latitude_1 <- read_excel("data/latitude.xlsx", sheet = "1700")
latitude_1

# Read the second sheet of latitude.xlsx:
latitude_2 <- read_excel("data/latitude.xlsx", sheet = 2)
latitude_2

# Put latitude_1 and latitude_2 in a list:
lat_list = list(latitude_1, latitude_2)
lat_list
str(lat_list) # list sestávající z dvou tibbles

# Apart from path and sheet, there are several other arguments you can specify in
# read_excel(). One of these arguments is called col_names.

# Import the the first Excel sheet of latitude_nonames.xlsx (R gives names):
latitude_3 = read_excel("data/latitude.xlsx", 
                        sheet = 3, 
                        col_names = FALSE)
latitude_3

# Import the the first Excel sheet of latitude_nonames.xlsx (specify col_names):
latitude_4 = read_excel("data/latitude.xlsx", 
                        sheet = 3, 
                        col_names = c("country", "latitude"))
latitude_4

# Print the summary of latitude_3
summary(latitude_3)

# Print the summary of latitude_4
summary(latitude_4)

# Another argument that can be very useful when reading in Excel files that are less
# tidy, is skip.
# With skip, you can tell R to ignore a specified number of rows inside the Excel
# sheets you're trying to pull data from.
# Have a look at this example:
read_excel("data/latitude.xlsx", skip = 15)

# In this case, the first 15 rows in the first sheet of "data.xlsx" are ignored.
# Pozor na posunutí matice!
# defalutně se funkce read_excel "mzslí", že jména proměnných jsou na 
# prvním nepřeskočeném (16.) řádku, proto nutné nastavit ručně
read_excel("data/latitude.xlsx", 
           skip = 15, 
           col_names = c("country", "latitude_1900"))

# Excel – readxl – slučování listů do jedné matice a chybějící
# hodnoty
latitude_all <- full_join(
  latitude_1, latitude_2, # sloučované datasety
  by = "country" # proměnná identifikující jednotlivé "případy"
)

# funkce full_join spojí sloupce dvou datasetů a 
# zachová všechny řádky obou datasetů

latitude_all
summary(latitude_all)

# Uložení dat ve formátu csv
write_excel_csv2(latitude_all, file = "data/latitude_all.csv")

# * Import dat z SPSS ------------------------
# Balíček foreign (základní součást R)

# Pomocná funkce, která proměnnou typu dbl+lbl přemění na faktor
fct_label <- function(x) {
  levs <- attributes(x)$labels
  labs <- names(levs)
  factor(x, levels = levs, labels = labs)
}

# Načtení dat
international <- read_spss("data/international.sav")
glimpse(international) # vidíme, že proměnná continent obsahuje numerické hodnoty
attributes(international$contint) # názvy úrovní najdeme až v atributech 

# Změníme ji na faktor, ať názvy úrovní vidíme přímo
international$contint <- fct_label(international$contint)

glimpse(international)
levels(international$contint)

# * Uložení dat ----------------------
# Uložení dat ve formátu .sav
write_sav(international, 
          file = "data/international_new.sav")

# Do formátu csv, který otevře většina programů včetně Excelu 
write_csv2(international, 
           file = "data/international_new.csv")

# Uložení do nativního R formátu
write_rds(international, 
          file = "data/international_new.rds")

read_rds("data/international_new.rds") # formát rds ukládá jeden datový objekt

# Kdybychom chtěli uložit všechny objekty v global environment
save.image(file = "data/all_objects.RData") # formát RData ukládá i více objektů

# A načíst
load("data/all_objects.RData")

# Nebo více objektů, ale ne všechny
save(planets, pools, file = "data/planets_and_pools.RData")



