##%######################################################%##
#                                                          #
####                    Uvedení do R                    ####
#                                                          #
##%######################################################%##


# První kroky a "rozkoukání se" ----------------------------
# Orientace v R Studiu
  # Konzole
  # Vytvoření nového skriptu
  # Environment/History/Connections
  # Files/Plots/Packages/Help/Viewer
# Vytvoření nového projektu přes: File - New Project
# (Nastavení vzhledu přes: Tools - Global Options - Appearance)
# Změna klávesových zkratek: Tools - Modify Keyboard Shortcuts


# Načtení balíčků ------------------------------
library(tidyverse)

# Základní operace -----------------------------
# * R jako kalkulačka ------------
# Sčítání
5 + 5 

# Odčítání
5 - 5 

# Násobení
3 * 5

# Dělení
(5 + 5) / 2 

# Umocňování
2^5

# Odmocňování
sqrt(9)
9^(1/2)

# Celočíselné dělení
16 %/% 6

# Zbytek celočíselném dělení
16 %% 6

# * Užitečné klávesové zkrakty ------------
# Psaní symbolů na české klávesnici skrze pravý alt:
# RAlt + x = #

# RAlt + F = []

# RAlt + B = {}

# RAlt + , = <

# RAlt + .= >

# RAlt + ů = $

# RAlt + C = &

# RAlt + š, poté jakýkoli znak = ^

# RAlt + ý, potéjakýkoli znak = ``

# Alternativa - přepnutí na anglickou klávesnici

### Modifikovatelné klávesové zkratky RStudia
# Alt + Shift + K   pro seznam klávesových zkratek RStudia
# Ctrl + Enter      pro spuštění aktuálního kódu na označeném řádku
# Ctrl + Alt + P    znovu spustí kód, který byl spuštěn naposledy
# Ctrl + Alt + R    spustí všechen kód
# Alt + -           vloží assigment operátor <- pro tvorbu objektů
# Alt + L           zabalí aktuální blok kód
# Alt + Shift + L   rozbalí aktuální blok kód
# Alt + O           zabalí všechen kód
# Alt + Shift + 0   rozbalí všechen kód
# Ctrl + Shift + R  vloží nový nadpis
# Ctrl + Shift + M  vloží pipe operátor %>% 

# * Tvorba objektů ----------------------------
# Objekt reprezentují hodnoty (např. "0" nebo "Jablko") nebo jiné objekty
# např. dataset je objekt obsahující jiné objekty - tj. jednotlivé proměnné

# Nové objekty lze vytvářet pomocí <- ve formě
# object_name <- value

# Přidělit objektu x hodnotu 42
x <- 42 

# vyvolat/prozkoumat objekt lze jenoduše napsáním jeho jména
x

# Doporučuji používat snake_case
# i_use_snake_case
# otherPeopleUseCamelCase
# some.people.use.periods
# And_aFew.People_RENOUNCEconvention
r_rocks <- 2 ^ 3

# Proč tento kód nefunguje? Je R "case sensitive"?
r_rock
R_rocks

# Vytvořte proměnnou my_age s hodnotou vašeho věku v letech
my_age <- 30

# Vyvolejte tuto proměnnou
my_age

# Vytvořte proměnnou year se současným rokem
year <- 2021

# Odečtěte my_age od year a vytvořte proměnnou birth_year
birth_year <- year - my_age

# Vyvolejte proměnnou birth_year
birth_year

### Základní typy objektů
# Změňte hodnotu my_numeric na vaše oblíbené číslo
my_numeric <- 0

# Změňte hodnotu my_character např. na jméno vaší oblíbené kapely
my_character <- "My favourite band"

# Změňte hodnotu my_logical na FALSE
my_logical <- TRUE

# Vyvolejte proměnné my_numeric, my_character i my_logical
my_numeric
my_character
my_logical

# Aplikujte funkci typeof() na objekty my_numeric, my_character i my_logical
typeof(my_numeric)
typeof(my_character)
typeof(my_logical)

# Vektory ----------------
# * Vlastnosti vektorů ------------------
# There are two types of vectors:
# Atomic vectors, of which there are six types: 
# logical, integer, double, character, complex, and raw. 
# Integer and double vectors are collectively known as numeric vectors.
 # Integers jsou celá čísla, doubles mohou obsahovat desetinná místa

# Lists, which are sometimes called recursive vectors because lists can contain 
# other lists.

# The chief difference between atomic vectors and lists is that atomic vectors 
# are homogeneous, while lists can be heterogeneous.
 # homogenní zde znamená, že všechny prvky jsou stejného typu, např. pouze
 # celá čísla
 # O atomických vektorech lze uvažovat jako o jednotlivých proměnných

# Every vector has two key properties:
# Its type, which you can determine with typeof().
letters
typeof(letters)

1:10
typeof(1:10)

typeof(c(TRUE, FALSE, TRUE))

# Its length, which you can determine with length().
x <- list("a", "b", 1:10)
length(x)

length(1:10)

# Vectors can also contain arbitrary additional metadata in the form of attributes. 
# These attributes are used to create augmented vectors which build 
# on additional behaviour. There are three important types of augmented vector:

# Factors are built on top of integer vectors.
# Dates and date-times are built on top of numeric vectors.
# Data frames and tibbles are built on top of lists.

# * Základní typy atomických vektorů --------------------------

### Logical
# Logical vectors are the simplest type of atomic vector because they can take 
# only three possible values: FALSE, TRUE, and NA
c(TRUE, TRUE, FALSE, NA)

### Numeric (číselné, numerické)
# Integer and double vectors are known collectively as numeric vectors. 
# In R, numbers are doubles by default. 
# To make an integer, place an L after the number:
typeof(1)
typeof(1L)

# The distinction between integers and doubles is not usually important, 
# but there are two important differences that you should be aware of:
# Doubles are approximations.
# Paměť počítače není neomezená, takže si pamatuje pouze určitý počet
# desetinných míst
x <- sqrt(2) ^ 2
x
x - 2

# Instead of comparing floating point numbers using ==, you should use 
# dplyr::near() which allows for some numerical tolerance.
x == 2
near(x, 2)

### Character
# Character vectors are the most complex type of atomic vector, 
# because each element of a character vector is a string, and a string can 
# contain an arbitrary amount of data.
x <- "This is a reasonably long string."
x

# * Konverze mezi typy ------------------------
# There are two ways to convert, or coerce, one type of vector to another:

# Explicit coercion happens when you call a function like as.logical(), 
# as.integer(), as.double(), or as.character()
as.integer(c(TRUE, FALSE, TRUE))
as.character(c(1, 2, 3, 4))
as.logical(c(0, 1, 0, 1))

# Implicit coercion happens when you use a vector in a specific context 
# that expects a certain type of vector.
x <- sample(1:20, 100, replace = TRUE)
x

y <- x > 10
y

sum(y)
mean(y)

# Složitější typ má přednost
c(TRUE, 0L)
typeof(c(TRUE, 0L))

c(TRUE, 0L, 2.5)
typeof(c(TRUE, 0L, 2.5))

c(TRUE, 0L, 2.5, "one")
typeof(c(TRUE, 0L, 2.5, "one"))

# * Ověření typu vektoru
# Sometimes you want to do different things based on the type of vector. 
# One option is to use typeof(). 
typeof(c(TRUE, FALSE))

# Another is to use a test function 
# which returns a TRUE or FALSE.
is_logical(c(TRUE, FALSE))
is_logical(c(0, 1))

is_integer(c(1L, 2L))
is_integer(c(1, 2))

is_double(c(1.2, 2.4))
is_double(c(1L, 2L))

is_numeric(c(1.2, 2.4))
is_numeric(c(1L, 2L))

is_character(c("1", "2"))
is_character(c(1, 2))

is_atomic(c(1, 2))
is_atomic(list(1, c(1, 2)))

is_list(c(1, 2))
is_list(list(1, c(1, 2)))

is_vector(c(1, 2))
is_vector(NULL)

# * Recyklace prvků vektoru -------------------
# Každé zřejmě uhádne, co se stane, když sečteme (vynásobíme, odečteme apod.) 
# vektory stejné délky
c(1, 2, 3) + c(4, 5, 6)
c(1, 2, 3) * c(4, 5, 6)
c(1, 2, 3) / c(4, 5, 6)

# Co když ale vektory nemají stejnou délku
# As well as implicitly coercing the types of vectors to be compatible, 
# R will also implicitly coerce the length of vectors. 
# This is called vector recycling, because the shorter vector is repeated, 
# or recycled, to the same length as the longer vector.

# same
c(1, 2, 3) + 10
c(1, 2, 3) + c(10, 10, 10)

# It’s intuitive what should happen if you add two vectors of the same length, 
# or a vector and a “scalar”, but what happens if you add two vectors 
# of different lengths?
1:10 + 1:2

# same as
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2)

# Here, R will expand the shortest vector to the same length as the longest, 
# so called recycling. This is silent except when the length of the longer 
# is not an integer multiple of the length of the shorter
1:10 + 1:3

# same as
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)

# * Pojmenování prvků vektoru ---------------
# All types of vectors can be named. You can name them during creation with c()
x <- c(x = 1, y = 2, z = 4)
x
names(x)
attributes(x)

# Or after the fact with names or purrr::set_names()
x <- c(1, 2, 4)
x

names(x) <-  c("x", "y", "z")
x

x <- c(1, 2, 4)
x <- set_names(x, c("x", "y", "z"))
x

# * Výběr prvků (subsetting ) --------------
# There are four types of things that you can subset a vector with:

# 1) A NUMERIC VECTOR CONTAINING ONLY INTEGERS. The integers must either be 
# all positive, all negative, or zero.
x <- c("one", "two", "three", "four", "five")
x[c(3, 2, 5)]

# By repeating a position, you can actually make a longer output than input:
x[c(1, 1, 1, 5, 5, 5, 2)]

# Negative values drop the elements at the specified positions:
x[c(-1, -3, -5)]
x[-c(1, 3, 5)]

# It’s an error to mix positive and negative values
x[c(1, -1)]

# 2) Subsetting with a LOGICAL VECTOR keeps all values corresponding to a TRUE value. 
# This is most often useful in conjunction with the comparison functions.
x <- c(10, 3, NA, 5, 8, 1, NA)
x

x[c(TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE)]
x[c(TRUE, FALSE)]

# All non-missing values of x
x[!is.na(x)]

# All values greater than 5 (or missing)
x[x > 5]

# All even (or missing!) values of x
x[x %% 2 == 0]

# 3) If you have a NAMED VECTOR, you can subset it with a CHARACTER VECTOR:
x <- c(abc = 1, def = 2, xyz = 5)
x[c("xyz", "def")]
x[c("xyz", "xyz", "xyz")]

# There is an important variation of [ called [[. [[ only ever extracts a single 
# element, and always drops names. It’s a good idea to use it whenever you want 
# to make it clear that you’re extracting a single item

### Exercises
# What does mean(is.na(x)) tell you about a vector x
x <- c(1, 2, 3, NA)
mean(is.na(x))
mean(!is.na(x))

# What happens when you subset with a positive integer that’s bigger than the 
# length of the vector? What happens when you subset with a name that doesn’t exist?
x <- c(a = 10, b = 20)

x[1:5]
x[c("a", "b", "c", "d", "e")]

# the [[ behaves differently. With an atomic vector, if [[ is given an index 
# outside the range of the vector or an invalid name, it raises an error.
x[[3]]

# * 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, c(2, 3), c("A", "B", "C"))
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(a = 1, b = 2, c = 3)
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(
  a = 1:3, 
  b = "a string", 
  c = pi, 
  d = list(-1, -5)
  ) 

str(a)

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

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

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

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

# * Augmentované vektory -----------------------
### Augmented vectors
# Atomic vectors and lists are the building blocks for other important vector 
# types like factors and dates. I call these augmented vectors, because 
# they are vectors with additional attributes

# ** 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:
x <- factor(
  c("a1", "a1", "b2", "c3"), 
  levels = c("a1", "b2", "c3")
  )
x
typeof(x)
attributes(x)
levels(x)

temps <- c("cold", "hot", "hot", "warm", "cold", "cold", "warm")
factor(temps)
# defaultní je pořadí úrovní podle abecedy

temps_fct <- factor(temps, levels = c("cold", "warm", "hot"))
temps_fct

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

# ** Datum a čas -----------------------
# Dates in R are numeric vectors that represent the number of days 
# since 1 January 1970.
x <- as.Date("1971-01-01")
unclass(x)
typeof(x)
attributes(x)

# Date-times are numeric vectors with class POSIXct that represent the number 
# of seconds since 1 January 1970. 
x <- as.POSIXct("1970-01-01 01:00", tz = "UTC")
unclass(x)
typeof(x)
attributes(x)

### Tibles and Dataframes
# Tibbles are augmented lists: they have class “tbl_df” + “tbl” + “data.frame”, 
# and names (column) and row.names attributes:
tb <- tibble(x = 1:5, y = 5:1)
tb
typeof(tb)
attributes(tb)

# The difference between a tibble/dataframe and a list is that all the elements of 
# a tibble/dataframe must be vectors with the same length.

# Traditional data.frames have a very similar structure
df <- data.frame(x = 1:5, y = 5:1)
typeof(df)
attributes(df)


# Example of working with vectors -------------------
c(421, "Reservoir Dogs", "death", FALSE, 10)

# Počet cursing words v několika Tarantinových filmech
movies <- c("Django Unchained", "Inglorious Basterds", "Jackie Brown",
            "Kill Bill: Vol. 1", "Kill Bill: Vol. 2", "Pulp Fiction", 
            "Reservoir Dogs")

profanities <- c(262, 58, 368, 57, 69, 469, 421)
profanities

names(profanities)
names(profanities)  <- movies
profanities
attributes(profanities)

# Výběr hodnot(y) z vektoru
profanities[c(2, 7)]
profanities[c(-2, -7)]

profanities[c("Reservoir Dogs", "Inglorious Basterds")]
profanities[c("Reservoir Dogs", "Inglorious Basterds")]

profanities[c(FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE)]
profanities[!c(FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE)]

# Vektorová aritmetika
# Sčítání vektorů
hell <-  c(10, 4, 10, 3, 1, 2, 12)
goddamn <-  c(28, 8, 27, 7, 5, 28, 10)

names(hell) <- movies
names(goddamn) <- movies

spirituality <-  hell + goddamn
spirituality_sum <- sum(spirituality)
spirituality_sum

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?
profanities
profanities > 100
profanities[profanities > 100]

# Zaznívalo ve filmech více slovo "hell", nebo "goddamn"?
hell < goddamn

# Ve kterém filmu zaznělo časti slovo "Hell" než "goddamn"?
movies
movies[hell > goddamn]

# * 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.
 # Since you are only working with rows and columns, a matrix is called twodimensional.

# sekvence čísel od 1 do 12
x <- seq(from = 1, to = 12)
x

# Kratší zápis
x <- 1:12
x

matrix(x, byrow = TRUE, nrow = 3)
matrix(x, byrow = FALSE, nrow = 3)
matrix(x, byrow = FALSE, ncol = 2)

profanities

deaths <- c(47, 48, 4, 63, 11, 7, 10)
names(deaths) <- movies
deaths

# Sloučení dvou vektorů do jednoho
c(profanities, deaths)

# Vytvořit matici
columns <- c("profanities", "deaths")

m <- matrix(
  c(profanities, deaths),
  byrow = FALSE,
  ncol = 2,
  dimnames = list(
    movies, # Labely pro řádky matice
    columns # Labely pro sloupce matice
  )
)
m


# Nastavení názvů řádků/sloupců až po vytvoření matice
m <- matrix(
  c(profanities, deaths),
  byrow = FALSE,
  ncol = 2
)
m

dimnames(m)
dimnames(m) <- list(
  movies, # Labely pro řádky matice
  columns # Labely pro sloupce matice
)
m

m <- matrix(
  c(profanities, deaths),
  byrow = FALSE,
  ncol = 2
)

rownames(m) <- movies
colnames(m) <- columns
m  

View(m)

# Součet/průměr řádků/sloupců
colSums(m)
colMeans(m)
rowSums(m)
rowMeans(m)

# Přidání sloupců
year <- c(2012, 2009, 1997, 2003, 2004, 1994, 1992)
year

m <- cbind(
  m, year
)
m

# Přidání řádků
`The Hateful Eight` <- c(107, 20, 2015)

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ů
m[8, ]
m[8, 3]
m[ , 2]

# Pomocí názvů řádků/sloupců
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 sledovaných filmech?
mean(m[, "deaths"])


# Jaký je Tarantino index (tj. počet mrtvých na počet nadávek) pro Inglorious Basterds?
m["Inglorious Basterds", "deaths"] / m["Inglorious Basterds", "profanities"]

# * Data frame --------------------------------------------------------------
# Data Frame je matice tak, jak ji chápeme při analýze dat
# A data frame has the variables of a data set as columns and the
# observations as rows

# Vyvolání Data Frame z R
data()
data(USArrests)
View(USArrests)

# Jak se zorientovat v Data Frame?
 # head() - show the first observations of a data frame
 # tail() - prints out the last observations in your data set
 # str() - struktura dat

head(USArrests)
head(USArrests, n = 10)

tail(USArrests)
tail(USArrests, n = 15)

str(USArrests)

# Tvorba dataframe
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

# Řazení
planets$diameter

order(planets$diameter)
order(planets$diameter, decreasing = TRUE)

planets[order(planets$diameter, decreasing = FALSE), ]
planets[order(planets$diameter, decreasing = TRUE), ]

# Co dělá tato funkce:
sort(planets$diameter)

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


# * 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
as_tibble(iris)

# 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(
  x = 1:5, 
  y = 1, 
  z = x ^ 2 + y
)

# It’s possible for a tibble to have column names that are not valid 
# R variable names, aka non-syntactic names. 
# For example, they might not start with a letter, or they might contain 
# unusual characters like a space. To refer to these variables, 
# you need to surround them with backticks

# Na české klávesnici RAlt + ý (pak jakýkoli znak)

tb <- tibble(
  `:)` = "smile", 
  ` ` = "space",
  `2000` = "number"
)
tb

# 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(
  ~x, ~y, ~z,
  
  "a", 2, 3.6,
  "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)
)

# Tibbles are designed so that you don’t accidentally overwhelm your console 
# when you print large data frames. But sometimes you need more output than 
# the default display. There are a few options that can help.

# First, you can explicitly print() the data frame and control the number of 
# rows (n) and the width of the display. width = Inf will display all columns:

nycflights13::flights %>% 
  print(n = 5, width = Inf)

# You can also control the default print behaviour by setting options:
# options(tibble.print_max = n, tibble.print_min = m): 
  # if more than n rows, print only m rows. 
options(tibble.print_max = 20, tibble.print_min = 10)

# Use options(tibble.print_min = Inf) to always show all rows.

# Use options(tibble.width = Inf) to always print all columns, 
# regardless of the width of the screen.

# A final option is to use RStudio’s built-in data viewer to get a scrollable 
# view of the complete dataset. 
# This is also often useful at the end of a long chain of manipulations.
nycflights13::flights %>% 
  View()

# 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)
)
df

# Extract by name
df$x

df[["x"]]

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


# To use these in a pipe, you’ll need to use the special placeholder .
df %>% 
  .$x

df %>% 
  .[["x"]]

# Exercises
# How can you tell if an object is a tibble? (Hint: try printing mtcars, 
# which is a regular data frame).
mtcars
is_tibble(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?
df <- data.frame(
  x = c(1, 2, 3), 
  y = c("a", "b", "c")
)

df$x
df[, "y"]
df[, c("x", "y")]  
  
df <- tibble(
  x = c(1, 2, 3), 
  y = c("a", "b", "c")
)

df[, "y"]
df[["y"]]

