5.1 Atomické vektory

Nejzákladnější datovou strukturou je v R atomický vektor. R nemá datovou strukturu pro skalár (jedinou logickou hodnotu, jediné číslo, znak nebo řetězec) – každý skalár je ve skutečnosti atomický vektor s jediným prvkem. Atomický vektor je vektor hodnot, jehož všechny prvky mají stejný typ (např. celé číslo). Atomické vektory se vytvářejí funkcí c() (od “concatenate”), která “slepí” jednotlivé hodnoty dohromady, přičemž provede automatickou konverzi (pokud je potřeba).

x <- c(1, 2, 3, 17)
print(x)
## [1]  1  2  3 17

Pomocí funkce c() je možné “slepit” i celé vektory:

x1 <- c(1, 2, 3)
x2 <- c(4, 5, 6, NA)
x <- c(x1, x2)
print(x)
## [1]  1  2  3  4  5  6 NA

Všechny prvky atomického vektoru musejí mít stejný typ. Pokud tedy při tvorbě atomického vektoru smícháte proměnné různých typů, dojde k automatické konverzi:

c(TRUE, 1, "ahoj")  # výsledek je vektor tří řetězců
## [1] "TRUE" "1"    "ahoj"

Jednotlivé prvky atomických vektorů mohou mít jména. Jména jsou uložena v atributu names. Je možné je zadat čtyřmi různými způsoby: přímo ve funkci c(), pomocí funkce attr(), pomocí speciální funkce names() nebo funkce setNames():

x <- c(a = 1, "good parameter" = 7, c = 17)
x
##              a good parameter              c 
##              1              7             17
attr(x, "names") <- c("A", "Good Parameter", "C")
x
##              A Good Parameter              C 
##              1              7             17
names(x) <- c("aa", "bb", "cc")
names(x)
## [1] "aa" "bb" "cc"
x
## aa bb cc 
##  1  7 17
setNames(x, c("A", "B", "C"))
##  A  B  C 
##  1  7 17

Pokud mají jednotlivé prvky vektorů přiřazená jména, vypisují se na obrazovku nad vlastní hodnoty.

Délku vektoru je možné zjistit pomocí funkce length():

length(x)
## [1] 3

Pozor: atomický vektor může mít i nulovou délku, pokud neobsahuje žádné prvky. (Podobně i další datové struktury mohou mít nulové rozměry, např. nulový počet řádků apod.) Prázdný vektor vznikne často tak, že z existujícího vektoru vyberete hodnoty pomocí podmínky, kterou žádný prvek vektoru nesplní (jak se vybírá část datové struktury uvidíte později):

x <- 1:9
length(x)
## [1] 9
y <- x[x > 10]  # vybereme prvky větší než 10, viz dále
y
## integer(0)
length(y)
## [1] 0

Prázdný vektor je možné vytvořit pomocí konstruktorových funkcí logical(), integer(), numeric(), character() apod., které mají jediný parametr, počet prvků. Pokud je zadaný počet prvků nulový, funkce vrátí prázdný vektor. Pokud je počet prvků kladný, vznikne vektor se zadanou délkou. To je užitečné např. v situaci, kdy si chcete dopředu připravit vektor určité délky, a později jej naplnit hodnotami. (Funkce numeric() má poněkud nekonzistentní název, protože vytváří vektor typu double.)

z <- numeric(0)  # parametr je délka vektoru
z
## numeric(0)
z <- numeric(10)  # vektor 10 hodnot
z
##  [1] 0 0 0 0 0 0 0 0 0 0

Některé vektory obsahují předvídatelné sekvence čísel. Pro vytváření takových vektorů existuje operátor dvojtečka (:) a speciální funkce seq() a rep() a jejich specializované varianty:

1:10   # vektor celých čísel 1 až 10
##  [1]  1  2  3  4  5  6  7  8  9 10
10:1   # vektor celých čísel sestupně 10 až 1
##  [1] 10  9  8  7  6  5  4  3  2  1
# sekvence od ... do
seq(from = 1, to = 10, by = 3)  # s daným krokem
## [1]  1  4  7 10
seq(from = 1, to = 10, length.out = 4)  # s danou délkou výsledku
## [1]  1  4  7 10
seq_along(c(1, 3, 17, 31))  # celá čísla od 1 do délky zadaného vektoru
## [1] 1 2 3 4
seq_len(7)  # celá čísla od 1 nahoru se zadanou nezápornou délkou
## [1] 1 2 3 4 5 6 7
# opakování hodnot ve vektoru
rep(c(1, 3), times = 5)  # celý vektor 5 krát
##  [1] 1 3 1 3 1 3 1 3 1 3
rep_len(c(1, 3), length.out = 5)  # celý vektor do délky 5
## [1] 1 3 1 3 1
rep(c(1, 3), each = 3)  # každý prvek 3 krát
## [1] 1 1 1 3 3 3
rep(1:6, each = 2, times = 3)
##  [1] 1 1 2 2 3 3 4 4 5 5 6 6 1 1 2 2 3 3 4 4 5 5 6 6 1 1 2 2 3 3 4 4 5 5 6 6

Složitější varianty použití funkce rep() viz dokumentace.

Pozor! Konstrukce vektoru pomoci operatoru dvojtecka je nekdy nebezpecna. Rekneme, ze chcete provest nejakou operaci pro kazdy prvek vektoru x a ze to chcete udelat pomoci cyklu for, viz oddil 7.2.1. Pri psani cyklu se casto prochazi hodnoty pomocneho vektoru k = 1:length(x). Pokud ma vektor x kladnou delku, je vse v poradku. Pokud vsak vektor x neobsahuje zadne hodnoty, pak ma nulovou delku. Cekali bychom, ze pomocny vektor k bude mit take nulovou delku, takze cyklus neprobehne ani jednou. To vsak neni pravda. Vektor k je v tomto pripade zkonstruovan jako 1:0, ma tedy hodnotu c(1, 0) a delku 2! Takova vec je zdrojem spatne dohledatelnych chyb. Je lepsi pouzit k = seq_along(x). Jeste lepsi je cyklum se vyhybat. R k tomu ma velmi uzitecne funkce typu map(), viz kapitola 10.

Na obrazovku se vektory vypisují tak, že se jejich jednotlivé hodnoty skládají vedle sebe do řádku. Pokud se všechny hodnoty na řádek nevejdou, začne se vypisovat na dalším řádku. Pokud nejsou jednotlivé prvky vektoru pojmenované, pak je každý řádek uvozen číslem v hranatých závorkách. To je index prvního prvku vektoru na daném řádku. Protože jsou prvky vektorů číslované přirozenými čísly (tj. první prvek má index 1), bude první řádek začínat [1]. Pokud další řádek začíná např. [31], znamená to, že první číslo na daném řádku je 31. prvek daného vektoru atd.

1:100
##   [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
##  [19]  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
##  [37]  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
##  [55]  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
##  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
##  [91]  91  92  93  94  95  96  97  98  99 100

Pokud jsou prvky vektoru pojmenované, pak R nevypisuje na začátek řádku indexy prvního prvku, ale vypisuje nad jednotlivé prvky jejich jména:

setNames(1:26, letters)
##  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z 
##  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

Poznámka: I když se vektory vypisují na obrazovku po řádcích, neznamená to že jsou v R vektory řádkové – nejsou ani řádkové, ani sloupcové (jako je to implicitně třeba v Matlabu). Hodnoty se vypisují po řádcích prostě pro úsporu místa.

R je vektorizovaný jazyk. To znamená, že veškeré aritmetické a logické operace a většina funkcí, která pracuje s vektory, provádí danou operaci na celých vektorech po prvcích. Pokud např. vynásobíte dva vektory \(x\) a \(y\), výsledkem bude vektor, jehož prvky budou násobky odpovídajících prvků obou vektorů, takže \(z_i = x_i \cdot y_i\):

x <- 1:6
y <- 2:7
x * y
## [1]  2  6 12 20 30 42
x ^ 2
## [1]  1  4  9 16 25 36

Pozor: pokud se délka vektorů liší, pak R automaticky “recykluje” kratší vektor, tj. opakuje jeho hodnoty znovu a znovu. Při tom vydá R varování jen v případě, že délka delšího vektoru není celočíselným násobkem délky kratšího vektoru:

x <- 1:2
y <- 1:6
x + y
## [1] 2 4 4 6 6 8
x * y
## [1]  1  4  3  8  5 12
y <- 1:7
x + y
## Warning in x + y: longer object length is not a multiple of shorter object
## length
## [1] 2 4 4 6 6 8 8

Otestovat, zda je promenna atomicky vektor, neni uplne snadne. R nabizi dve potrebne funkce, z nichz vsak zadna sama o sobe nestaci. Funkce is.atomic() vrati hodnotu TRUE, pokud je dana promenna atomicka (tj. vsechny jeji prvky maji stejny datovy typ). Tuto hodnotu vsak nevraci jen pro atomicke vektory, ale i pro atomicke matice, viz oddil 5.2. Funkce is.vector() vraci logickou hodnotu TRUE, pokud je promenna vektor; vektory vsak v R nemuseji byt nutne atomicke; funkce proto vraci TRUE i pro neatomicke vektory (seznamy), viz oddil 5.3. Zda proměnná obsahuje atomický vektor proto musíme otestovat spojením těchto funkcí:

is.atomic(x)  # x je atomická, tj.\ homogenní proměnná
## [1] TRUE
is.vector(x)  # x je vektor
## [1] TRUE
is.atomic(x) & is.vector(x)  # x je atomický vektor
## [1] TRUE

Někdy je potřeba získat z datové struktury jen vybrané prvky: z vektoru jednotlivé prvky, z matice vybrané řádky nebo sloupce apod. K tomu slouží subsetování. Subsetování lze použít nejen k získání vybraných prvků z datové struktury, ale také k jejich nahrazení nebo doplnění. K základnímu subsetování slouží hranaté závorky ([]). V nich se určí indexy prvků, které je třeba vybrat. Prvky mohou být vybrány třemi způsoby: pomocí svých indexů, pomocí svých jmen a nebo pomocí logických hodnot. Ukážeme si to nejprve na atomických vektorech.

1. Výběr pomocí číselných indexů. Prvky atomických vektorů jsou číslované přirozenými čísly \(1,\ldots,N\), kde \(N\) je délka vektoru (tj. první prvek vektoru má index 1, nikoli 0). Při výběru prvků pomocí indexů se vyberou prvky s danými indexy (pokud jsou indexy kladné), nebo se vynechají prvky s danými indexy (pokud jsou indexy záporné). Indexování pomocí kladných a záporných čísel nelze míchat. Index 0 se tiše ignoruje.

# vektor letters obsahuje 26 malých písmen anglické abecedy
x <- letters[1:12]  # prvních dvanáct písmen abecedy
x
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
x[1]  # první prvek
## [1] "a"
x[3]  # třetí prvek
## [1] "c"
x[length(x)]  # poslední prvek
## [1] "l"
x[3:6]  # třetí až šestý prvek včetně
## [1] "c" "d" "e" "f"
x[c(2, 3, 7)]  # druhý, třetí a sedmý prvek
## [1] "b" "c" "g"
x[c(-1, -3)]  # vynechají se první a třetí prvek
##  [1] "b" "d" "e" "f" "g" "h" "i" "j" "k" "l"

2. Výběr pomocí jmen prvků. Pokud mají prvky vektoru jména, je možné vybírat pomocí vektoru jejich jmen (zde samozřejmě nejde vynechávat pomocí znaménka minus, protože R nemá záporné řetězce):

x <- c(c = 1, b = 2, a = 3)
x
## c b a 
## 1 2 3
x["a"]  # prvek s názvem a, tj. zde poslední prvek
## a 
## 3
x[c("b", "c")]  # prvky s názvy b a c
## b c 
## 2 1

3. Výběr pomocí logických hodnot. R vybere prvky, které jsou indexovány logickou hodnotou TRUE a vynechá ostatní. Pozor: pokud je logický vektor kratší než subsetovaný vektor, pak se recykluje!

x <- 1:12
x
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12
x[c(TRUE, TRUE, FALSE)]
## [1]  1  2  4  5  7  8 10 11

Výběr pomocí logických hodnot je užitečný zejména v situaci, kdy chceme vybrat prvky, které splňují nějakou podmínku:

x[x > 3 & x < 11]  # vybere prvky, které jsou větší než tři a menší než 11
## [1]  4  5  6  7  8  9 10
x[x < 3 | x > 11]  # vybere prvky, které jsou menší než tři nebo větší než 11
## [1]  1  2 12

Subsetování lze využít k nahrazení prvků jednoduše tak, že se do výběru uloží nová hodnota, která nahradí starou:

x <- c(1:3, NA, 5:7)
x
## [1]  1  2  3 NA  5  6  7
x[7] <- Inf  # nahrazení poslední hodnoty nekonečnem
x
## [1]   1   2   3  NA   5   6 Inf
x[is.na(x)] <- 0  # nahrazení všech hodnot NA nulou
x
## [1]   1   2   3   0   5   6 Inf
x[length(x) + 1] <- 8  # přidání nové hodnoty za konec vektoru
x
## [1]   1   2   3   0   5   6 Inf   8

Pozor: postupné rozšiřování datových struktur vždy o několik málo prvků je výpočetně velmi neefektivní, protože R musí (téměř) pokaždé alokovat nové místo v paměti, do něj zkopírovat staré hodnoty a na konec přidat nový prvek. Mnohem efektivnější je naráz alokovat velký blok paměti, do něj postupně uložit hodnoty a blok na konci případně zkrátit:

x <- numeric(1e6)  # alokace prázdného vektoru o milonu prvků
x[1] <- 1          # přidání prvků (další řádky vynechány)
n <- 7654          # skutečný počet vložených prvků
x <- x[1:n]        # zkrácení vektoru na potřebnou délku

Ekvivalentně je vhodné postupovat v případě všech homogenních datových struktur.

Pozor: numeric() vytvoří vektor samých nul. Možná je lepší použít rep(NA_real_, 1e6), které vytvoří reálný vektor hodnot NA. Většina lidí však používá funkce numeric(), character() apod.

V R je možné výběry ze všech datových struktur řetězit – následující výběr vybírá z výsledku předchozího výběru:

v <- 1:10
v[6:10]     # 6. až 10. prvek v
## [1]  6  7  8  9 10
v[6:10][2]  # druhý prvek z výběru 6. až 10. prvku v
## [1] 7

Do zřetězeného výběru je obvykle možné dosazovat hodnoty:

v[6:10][2] <- NA
v
##  [1]  1  2  3  4  5  6 NA  8  9 10