---
title: "Co váží „typický“ savec?"
subtitle: "První setkání s daty a popisem jedné proměnné"
lang: cs
filters:
  - ../theme/semantic-boxes.lua
format:
  html:
    toc: true
    toc-depth: 3
    toc-title: "Obsah"
    number-sections: true
    code-fold: false
    code-summary: "Zobrazit kód v R"
    embed-resources: true
    theme: [flatly, ../theme/skripta_theme.scss]
    highlight-style: github
    include-in-header:
      - "../theme/fonts-include.html"
      - "../theme/skripta-favicon.html"
  typst:
    toc: true
    toc-depth: 3
    number-sections: true
    output-file: "skripta_raw.pdf"
    include-in-header:
      - "skripta_theme.typ"
      - "skripta-logo.typ"
date: 2026/07/26
date-format: long
date-modified: last-modified
---

```{r}
#| label: nastaveni
#| include: false
if (!require("here")) install.packages("here")

here::i_am("Learning_materials/skripta.qmd")

if (!require("tidyverse")) install.packages("tidyverse")
if (!require("ggbeeswarm")) install.packages("ggbeeswarm")
if (!require("glossary")) install.packages("glossary")

library(tidyverse)
library(ggbeeswarm)
library(glossary)

# Načteme společný kurzový vzhled grafů před úpravami pro tuto lekci.
source(here::here("R", "set_r_theme.R"))

# Slovníček: při práci v kurzovém workspace použijeme přímo kanonický
# soubor; vzdálené načtení zůstává zálohou pro samostatný checkout.
local_pojmy <- here::here("..", "slovnik", "pojmy.yaml")
if (!file.exists(local_pojmy)) {
  local_pojmy <- tempfile(fileext = ".yaml")
  tryCatch(
    {
      download.file(
        url = paste0(
          "https://raw.githubusercontent.com/",
          "CUNI-NATUR-Biostatistics/slovnik/main/pojmy.yaml"
        ),
        destfile = local_pojmy,
        quiet = TRUE
      )
    },
    error = function(e) {
      message("Glossary YAML unavailable: ", conditionMessage(e))
    }
  )
}
if (file.exists(local_pojmy)) {
  glossary::glossary_path(local_pojmy)
}

local_render_glossary <-
  here::here("..", "slovnik", "R", "Functions", "render_glossary_term.R")
if (file.exists(local_render_glossary)) {
  source(local_render_glossary)
} else {
  tryCatch(
    {
      source(
        paste0(
          "https://raw.githubusercontent.com/",
          "CUNI-NATUR-Biostatistics/slovnik/main/",
          "R/Functions/render_glossary_term.R"
        )
      )
    },
    error = function(e) {
      source(here::here("R/Functions/render_glossary_term.R"))
    }
  )
}
```

```{r}
#| label: nastaveni-slovnik
#| echo: false
#| message: false
#| results: asis
if (knitr::is_html_output()) {
  glossary::glossary_style(
    color = "#5D2890",
    text_decoration = "underline",
    def_bg = "#FFFFFF",
    def_color = "#2E2E2E"
  )
  cat(
    "<style>",
    "a.glossary:hover .def { display: inline-block; }",
    "a.glossary:hover .def::after {",
    "  content: ' '; position: absolute; top: 100%; left: 50%;",
    "  margin-left: -5px; border-width: 5px; border-style: solid;",
    "  border-color: #FFFFFF transparent transparent transparent;",
    "}",
    "a.glossary:active .def { display: none; }",
    "a.glossary:active .def::after { display: none; }",
    "</style>",
    "<script>",
    "document.addEventListener('DOMContentLoaded', function() {",
    "  document.querySelectorAll('a.glossary').forEach(function(a) {",
    "    a.addEventListener('click', function(e) { e.preventDefault(); });",
    "  });",
    "});",
    "</script>",
    sep = "\n"
  )
}
```
```{r}
#| label: nastaveni-vizualizace
#| echo: false
#| message: false
#| warning: false

col_data <- "#6B7280"
col_mean <- "#F3A712"
col_median <- "#5D2890"
col_fill <- "#D8C9E8"

ggplot2::theme_set(
  theme_biostat() +
    ggplot2::theme(
      panel.grid.minor = ggplot2::element_blank(),
      plot.title = ggplot2::element_text(
        face = "bold",
        colour = "#2E2E2E"
      ),
      strip.background = ggplot2::element_rect(
        fill = "#F0EDE8",
        color = "#8A8A8A"
      ),
      strip.text = ggplot2::element_text(
        face = "bold",
        colour = "#5D2890"
      )
    )
)
```

## Vítejte v biostatistice

Biostatistika pomáhá převést biologickou otázku na postup, který lze
zkontrolovat: **co jsme pozorovali, co jsme změřili, jak jsme data zobrazili a
co z nich smíme tvrdit**. Budeme se opakovaně vracet k cestě:

> biologická otázka → data → graf → model → kontrola → interpretace

V této lekci zůstaneme u prvního statistického kroku: jak poctivě popsat
**jednu `r render_glossary_term("promenna", display = "proměnnou")`**.

### Jak jsou kurz a materiály uspořádány

| Součást | K čemu slouží | Jak s ní pracovat |
|---|---|---|
| Přednáška | Společné přemýšlení nad biologickou otázkou, grafy a interpretací | Hlasujte, porovnávejte vysvětlení a ptejte se, co výsledek skutečně znamená. |
| Praktické cvičení | Samostatná práce s daty a R s podporou vyučujících | Kód zkoušejte, měňte a průběžně vysvětlujte vlastními slovy. |
| Tyto podklady | Úplnější vysvětlení a reprodukovatelné příklady | Čtěte je před výukou nebo se k nim vraťte při opakování. |
| Výstupy v HTML a PDF | Dvě podoby stejného obsahu | HTML nabízí interaktivní prvky; PDF se hodí pro souvislé čtení a poznámky. |

### Kde najdete materiály a informace

**Hlavním veřejným rozcestníkem je [web kurzu (HUB)](https://cuni-natur-biostatistics.github.io/).** Na stránce [Materiály](https://cuni-natur-biostatistics.github.io/materialy.html) najdete pro každou zveřejněnou lekci stabilní studentské verze:

| Materiál | Dostupné podoby | K čemu slouží |
|---|---|---|
| Skripta | HTML; PDF pro tisk | Úplnější výklad pro přípravu, samostudium a opakování |
| Prezentace | HTML; PDF pro tisk | Stručnější záznam společné práce na přednášce |
| R skripty | soubory s kódem | Praktická práce s daty v R |
| Data | datové soubory | Data potřebná pro praktickou práci a samostatné procvičování |

### Doporučená literatura

K absolvování kurzu **stačí materiály zveřejněné na webu kurzu (HUB)**:
skripta, prezentace, R skripty a data. Literatura je nepovinná a hodí se, když
chcete látku vidět z jiného úhlu nebo si ji procvičit na dalších příkladech.
Požadavky kurzu určují tyto materiály, ne uvedené knihy.

**Knihy**

| Zdroj | K čemu se hodí |
|---|---|
| Lepš, J., Šmilauer, P. (2024): *Biostatistika*, 2. přepracované vydání. Nakladatelství Jihočeské univerzity, České Budějovice. ISBN 978-80-7694-066-6. (česky) | Česká učebnice statistiky pro biology s postupy v programech Statistica a R. |
| Crawley, M. J. (2013): *The R Book*, 2. vydání. John Wiley & Sons, Chichester. (anglicky) | Rozsáhlá příručka k R a statistickým postupům v něm. |
| Dalgaard, P.: *Introductory Statistics with R*. Springer. (anglicky) | Stručný úvod do statistiky s ukázkami v R. |

**Online zdroje v angličtině**

| Zdroj | K čemu se hodí |
|---|---|
| Wickham, H., Çetinkaya-Rundel, M., Grolemund, G.: [*R for Data Science*](https://r4ds.hadley.nz/), 2. vydání. | Práce s daty a grafy v R. |
| Ismay, C., Kim, A. Y., Valdivia, A.: [*Statistical Inference via Data Science: A ModernDive into R and the Tidyverse*](https://moderndive.com/v2/), 2. vydání. | Statistické myšlení a R krok za krokem. |

Online zdroje mohou používat jiný styl zápisu R kódu než naše materiály nebo
pokrývat širší témata. Úplný a aktuální seznam literatury najdete na stránce
[Jak pracovat s materiály](https://cuni-natur-biostatistics.github.io/jak-pracovat-s-materialy.html)
na webu kurzu (HUB).

```{=typst}
#pagebreak()
```

Různé kurzové systémy mají odlišné úlohy:

| Systém | K čemu slouží |
|---|---|
| **Web kurzu (HUB)** | Aktuální informace o kurzu, rozvrh, pravidla hodnocení, veřejné studijní materiály a archiv semestrů |
| **SIS** | Zápis do předmětu a skupin, termíny zkoušek a oficiální studijní evidence |
| **Moodle** | Testy, zadání, odevzdávání, individuální výsledky a oznámení určená zapsaným studentům |

### Účast, zápočet a zkouška

Účast na přednáškách a praktických cvičeních je dobrovolná. Ve výuce získáte
vysvětlení, podporu a zpětnou vazbu; při samostudiu najdete požadované znalosti
ve skriptech a R skriptech. **Stejné kompetence však musí prokázat každý.**

- **Praktický zápočet** ověřuje, zda dokážete samostatně provést a vysvětlit
  základní analýzu malého datasetu v R.
- **Závěrečná zkouška** ověřuje porozumění analytickým rozhodnutím,
  interpretaci, diagnostice a nejistotě, nikoli psaní syntaxe zpaměti.

::: {.box-rule title="AI při učení a hodnocení"}
Při učení můžete AI používat. U zápočtu a zkoušky pracujete samostatně bez
internetu a AI.
:::

Aktuální [pravidla hodnocení](https://cuni-natur-biostatistics.github.io/hodnoceni.html) jsou uvedena na webu kurzu (HUB). Termíny zkoušek a zápis na ně jsou v SIS. Termíny praktického zápočtu, odevzdávání, individuální výsledky a neveřejné organizační pokyny jsou v Moodle.

## Jak číst skripta

Tento dokument vznikl v Quarto, ale pro jeho čtení nemusíte Quarto znát ani
instalovat. Stejný obsah dostáváte jako webovou stránku (HTML) a jako PDF.
Liší se hlavně způsob, jak se v něm pohybujete.

### Doporučený způsob čtení

1. Nejdříve si přečtěte **výsledky učení**. Říkají, co byste po dokončení
   kapitoly měli umět.
2. U otázky, hlasování nebo úkolu se zastavte a zkuste odpovědět dříve, než
   budete pokračovat.
3. Graf nebo tabulku nejprve sami popište. Teprve potom čtěte vysvětlení pod
   nimi.
4. Kód nemusíte memorovat. Sledujte, jaká data do něj vstupují, co s nimi
   příkaz dělá a jaký výsledek vrací.
5. Na konci se vraťte ke shrnutí a ověřte si, zda už dokážete vysvětlit hlavní
   myšlenky vlastními slovy.

### HTML a PDF

Následující blok je zároveň ukázkou **záložek** (anglicky *tabs*, technicky
*tabset*). V HTML mezi záložkami přepínáte kliknutím. V PDF jsou jejich obsahy
vytištěné postupně za sebou.

::: {.panel-tabset}
#### HTML

- Obsah na okraji stránky umožňuje přejít přímo do vybrané části.
- Projděte všechny záložky; současně je viditelná jen jedna.
- Rámeček s šipkou lze rozbalit a zase sbalit.
- U podtrženého odborného pojmu se po najetí kurzorem zobrazí stručné
  vysvětlení.
- U delšího bloku kódu se po najetí objeví tlačítko pro jeho zkopírování.

#### PDF

- K orientaci slouží obsah, nadpisy a čísla stránek.
- Obsah všech záložek je vytištěný postupně, takže žádná část nechybí.
- Sbalitelné rámečky jsou rozbalené. U odpovědi se proto zastavte ještě před
  jejím přečtením.
- Význam odborných pojmů najdete v odkazovaném online slovníku.
:::

### Co znamenají rámečky a další značky

| Značka | Jak s ní pracovat |
|---|---|
| **Důležité** | Hlavní pojem nebo závěr, který byste si měli odnést. |
| **Pozor** | Častá chyba nebo omyl. Zkontrolujte, že rozumíte, proč je daný postup problematický. |
| **Poznámka** | Podpůrné vysvětlení, příklad nebo kontext k hlavnímu výkladu. |
| **Doplňující** | Volitelná technická či rozšiřující informace. Při prvním čtení ji můžete přeskočit. |
| **Otázka**, **Hlasování**, **Úkol** | Výzva k vlastní odpovědi nebo činnosti. Nejdříve se rozhodněte sami. |
| **Odpověď** | Kontrola po vlastním pokusu. V HTML ji otevřete kliknutím; v PDF je vytištěná. |
| Blok kódu a jeho výstup | Reprodukovatelný záznam postupu: co jsme zadali počítači a co počítač vrátil. |
| Podtržený odborný pojem | Odkaz na stručnou definici v online slovníku. |

Význam nese především nadpis rámečku. Barva pomáhá s orientací, ale není nutné
si ji pamatovat.

::: {.box-data collapse="true" title="Doplňující: rozbalovací rámeček"}

Tento rámeček obsahuje volitelné rozšíření. V HTML jej můžete rozbalit; v PDF
je vytištěný celý.
:::

### Jak číst kód

Každý řádek kódu, který vytváří výsledek, je v těchto materiálech viditelný,
abyste mohli zkontrolovat, odkud se číslo nebo graf vzaly. Kód si nemusíte
pamatovat. Při čtení se ptejte: **Jaká data vstupují? Co příkaz dělá? Jakou
odpověď dostáváme?** Řádky začínající znakem `#` jsou komentáře pro čtenáře;
počítač je nevykonává.

## Výsledky učení

Po prostudování materiálů dokážete:

- vysvětlit, co v tabulce představuje jeden řádek, vytvořit z několika měření
  vektor v R a zkontrolovat jej pomocí `length()` a `head()`;
- přečíst bodový graf,
  `r render_glossary_term("histogram", display = "histogram")`, graf hustoty,
  `r render_glossary_term("sloupcovy-graf", display = "sloupcový graf")` a
  `r render_glossary_term("boxplot", display = "krabicový graf")`
  a popsat, co každý z nich ukazuje a skrývá;
- vysvětlit, proč data zobrazujeme dříve, než je shrneme jedním číslem;
- najít a interpretovat
  `r render_glossary_term("prumer", display = "průměr")`,
  `r render_glossary_term("median", display = "medián")`,
  `r render_glossary_term("kvantil", display = "kvartily")`,
  `r render_glossary_term("iqr", display = "IQR")`, minimum, maximum a
  `r render_glossary_term("smerodatna-odchylka", display = "směrodatnou odchylku")`
  v číslech i na grafu;
- rozlišit `r render_glossary_term("spojita-promenna", display = "spojitou")`,
  `r render_glossary_term("diskretni-promenna", display = "diskrétní")`,
  `r render_glossary_term("nominalni-promenna", display = "nominální")` a
  `r render_glossary_term("ordinalni-promenna", display = "ordinální")`
  `r render_glossary_term("promenna", display = "proměnnou")` a vybrat pro ni
  smysluplný první graf a shrnutí.

## Datová detektivka: kolik váží „typický“ savec?

```{r}
#| label: hodnoty-pro-uvodni-titulky
#| echo: false
#| message: false
#| warning: false
vec_hmotnost_pro_titulky <- ggplot2::msleep[["bodywt"]]
prumer_hmotnost_pro_titulky <- mean(vec_hmotnost_pro_titulky)
median_hmotnost_pro_titulky <- median(vec_hmotnost_pro_titulky)
```

V tabulce máme hmotnost `r length(vec_hmotnost_pro_titulky)` druhů savců.
Chceme odpovědět na zdánlivě jednoduchou otázku:

> **Kolik váží „typický“ savec v této tabulce?**

Představte si, že ze stejných dat vyšly dva smyšlené novinové články.

::: {.box-question title="Smyšlený titulek A"}

**Vědci spočítali: „Průměrný savec váží
`r formatC(prumer_hmotnost_pro_titulky, format = "f", digits = 0, decimal.mark = ",")`
kg.“**
:::

::: {.box-question title="Smyšlený titulek B"}

**Jiná analýza stejných dat tvrdí: „Běžný savec váží jen
`r formatC(median_hmotnost_pro_titulky, format = "f", digits = 2, decimal.mark = ",")`
kg.“**
:::

### Hlasování

Který titulek je podle vás nejpravděpodobněji správný?

- A) Správný je pouze titulek A.
- B) Správný je pouze titulek B.
- C) Obě čísla mohou být vypočtena správně.
- D) Bez dalších informací nelze rozhodnout.

Než budete pokračovat, vyberte jednu odpověď a napište si **jednu větu**, která
ji zdůvodňuje. Zatím nepotřebujete znát názvy výpočtů. Potřebujete pouze
rozpoznat, jaké informace vám chybějí.

::: {.box-result title="Odpověď zatím odložíme"}

Nejdříve se naučíme sledovat cestu od měření přes tabulku a graf až k číselnému
shrnutí. K oběma titulkům se vrátíme ve chvíli, kdy budeme umět posoudit nejen
výsledek výpočtu, ale také tvar dat.
:::

## Od měření k tabulce a vektoru

Výzkumníci studovali spánkové vzorce savců a zaznamenali, že gepard spí
**12,1 hodiny za den**. Jedno takové pozorování můžeme zapsat jako jeden řádek
tabulky: název druhu, sledovanou proměnnou, jednotku a naměřenou hodnotu.

Když podobná pozorování spojíme pro více druhů, vznikne datová tabulka. Dataset
`msleep` obsahuje údaje o spánku a tělesné hmotnosti různých druhů savců a
vychází z publikovaných biologických údajů. Každý řádek představuje
**jeden zastoupený druh**, nikoli jednoho jednotlivého savce.

Představme si terénní nebo laboratorní práci, ze které taková tabulka vzniká.
Výzkumníci pro každý druh shromáždí nebo převezmou měření, zapíší název druhu,
jednotku a hodnotu a přidají je jako nový řádek. Naší
`r render_glossary_term("jednotka-pozorovani", display = "jednotkou pozorování")`
je zastoupený druh. My začneme jedinou
`r render_glossary_term("promenna", display = "proměnnou")`:
**celkovou dobou spánku za den v hodinách** (`sleep_total`).

```{r}
#| label: pripravit-zakladni-data
#| echo: false
#| message: false
#| warning: false
data_savci <-
  ggplot2::msleep |>
  dplyr::transmute(
    druh = name,
    rod = genus,
    potrava = dplyr::recode(
      vore,
      "carni" = "masožravec",
      "herbi" = "býložravec",
      "insecti" = "hmyzožravec",
      "omni" = "všežravec",
      .missing = "neuvedeno"
    ),
    rad = order,
    ochrana = conservation,
    spanek_h = sleep_total,
    hmotnost_kg = bodywt,
    velikost = cut(
      bodywt,
      breaks = quantile(
        bodywt,
        probs = c(0, 1 / 3, 2 / 3, 1),
        na.rm = TRUE
      ),
      labels = c("lehký", "střední", "těžký"),
      include.lowest = TRUE,
      ordered_result = TRUE
    )
  )

data_spanek <-
  data_savci |>
  tidyr::drop_na(spanek_h)

vec_spanek_h <- data_spanek[["spanek_h"]]
```

### Čtyři skutečné záznamy

Podívejme se na první čtyři řádky. Hodnota v posledním sloupci je číslo, které
by výzkumník zapsal do tabulky.

```{r}
#| label: prvni-ctyri-zaznamy
#| echo: false
#| message: false
#| warning: false
data_spanek |>
  dplyr::slice_head(n = 4) |>
  dplyr::transmute(
    `Druh (species)` = druh,
    `Celkový spánek za den (sleep total; h)` = spanek_h
  ) |>
  knitr::kable(
    align = c("l", "r")
  )
```

### Stejné hodnoty jako vektor v R

**Vektor** je uspořádaná řada hodnot stejného základního typu.
<!-- TODO: add slug vektor to pojmy.yaml -->
Čtyři hodnoty z tabulky můžeme do R zapsat pomocí funkce `c()`:

```{r}
#| label: vytvorit-maly-vektor-spanku
#| echo: true
#| eval: true
vec_spanek_ukazka <-
  c(
    12.1, # Cheetah
    17.0, # Owl monkey
    14.4, # Mountain beaver
    14.9  # Greater short-tailed shrew
  )

vec_spanek_ukazka
```

Každá hodnota má stejný význam i jednotku: počet hodin spánku za den pro jeden
zastoupený druh.

U celé tabulky nemusíme `r length(vec_spanek_h)` čísel opisovat ručně. Vybereme
sloupec `sleep_total` přímo z datového rámce:

```{r}
#| label: vybrat-vektor-spanku
#| echo: true
#| eval: true
# Vybereme jeden sloupec z původní tabulky.
vec_spanek_h <-
  ggplot2::msleep[["sleep_total"]]
```

### První kontrola vektoru

Než začneme počítat nebo kreslit, zkontrolujeme dvě jednoduché věci:

1. **Kolik hodnot máme?**
2. **Vypadají první hodnoty jako očekávaná měření v hodinách?**

```{r}
#| label: zkontrolovat-delku-vektoru
#| echo: true
#| eval: true
length(vec_spanek_h)
```

```{r}
#| label: zobrazit-prvni-hodnoty
#| echo: true
#| eval: true
head(
  x = vec_spanek_h,
  n = 10
)
```

`length()` potvrzuje počet hodnot. `head()` ukazuje začátek vektoru, takže
rychle odhalíme například omylem načtený textový sloupec nebo nečekané jednotky.
Argument `n = 10` říká, že chceme zobrazit **prvních deset hodnot**; jiné číslo
za `n =` by změnilo počet zobrazených hodnot. Ani jedna kontrola ale ještě
neukazuje tvar celého souboru hodnot.

::: {.box-data collapse="true" title="Doplňující: integer a double jako dva způsoby uložení čísel"}

R ukládá `5L` jako celé číslo typu `integer` a `5` jako číslo typu `double`:

```r
typeof(5L) # "integer"
typeof(5)  # "double"
```

Jde o **technický způsob uložení čísla v počítači**, nikoli automaticky o
statistický typ `r render_glossary_term("promenna", display = "proměnné")`.
Zaokrouhlená tělesná hmotnost `70` může být spojité
měření uložené jako `double`; počet pěti mláďat může být diskrétní proměnná
uložená jako `integer`. O statistickém typu rozhoduje význam hodnot.
:::

### Jak vypadá celý datový rámec?

Vektor drží jednu proměnnou. Původní datový rámec drží více proměnných vedle
sebe. Každý řádek stále představuje jeden druh.

```{r}
#| label: prohlednout-datovy-ramec
#| echo: true
#| eval: true
# Počet řádků a sloupců původních dat.
dim(ggplot2::msleep)

# Prvních šest řádků původních dat.
head(ggplot2::msleep, n = 6)
```

| Otázka | Odpověď pro `msleep` |
|---|---|
| Co představuje jeden řádek? | jeden zastoupený druh savce |
| Co představuje sloupec `sleep_total`? | celkovou dobu spánku za den v hodinách |
| Co představuje sloupec `bodywt`? | tělesnou hmotnost druhu v kilogramech |
| Je jeden řádek jeden jedinec? | ne; druh je zde shrnut jednou hodnotou |

::: {.box-rule title="Druh není jedinec"}

Řádek reprezentuje hodnotu vybranou pro **druh**. Slon africký a drobný rejsek
mají v tabulce každý právě jeden řádek. Výsledek proto popisuje zastoupené
druhy, nikoli `r render_glossary_term("cetnost", display = "četnost")` nebo
hmotnost všech savčích jedinců na Zemi.
:::

::: {.box-data collapse="true" title="Doplňující: odkud data pocházejí a co v nich chybí"}

Dataset `msleep` má podle
[dokumentace balíčku ggplot2](https://ggplot2.tidyverse.org/reference/msleep.html)
`r nrow(ggplot2::msleep)` řádků a `r ncol(ggplot2::msleep)`
`r render_glossary_term("promenna", display = "proměnných")`.
Údaje o spánku a hmotnosti vycházejí z práce Savage a West (2007),
[A quantitative, theoretical framework for understanding mammalian sleep](https://pubmed.ncbi.nlm.nih.gov/17215372/).
Dokumentace uvádí, že taxonomický řád, stav ochrany a typ potravy byly doplněny
z Wikipedie.

Ne všechny buňky jsou vyplněné: v celé tabulce chybí
`r sum(is.na(ggplot2::msleep))` hodnot. Celková doba spánku a tělesná hmotnost
jsou úplné, ale například stav ochrany chybí u
`r sum(is.na(ggplot2::msleep[["conservation"]]))` druhů a typ potravy u
`r sum(is.na(ggplot2::msleep[["vore"]]))` druhů. Chybějící hodnota není nula;
znamená, že údaj v tabulce nemáme.
:::

::: {.box-data collapse="true" title="Doplňující: výběr není celá populace"}

`r render_glossary_term("vyber", display = "Výběr")` je soubor pozorování, která máme skutečně k dispozici. Cílová populace je širší celek, o kterém bychom chtěli něco říct. Dataset `msleep` obsahuje zastoupené druhy savců, ale není automaticky náhodným průřezem všech savců ani všech jedinců. `r render_glossary_term("prumer", display = "Průměr")`, `r render_glossary_term("median", display = "medián")` nebo `r render_glossary_term("smerodatna-odchylka", display = "SD")` proto nejprve přesně popisují tento soubor; možnost zobecnění závisí také na tom, jak byly druhy vybrány a jak vznikly jejich souhrnné hodnoty.

Dvě tabulky mohou mít stejný počet řádků a stejně přesně vypočtené statistiky, ale různou vypovídací hodnotu. Pokud v jedné chybějí například málo prozkoumané noční druhy, samotný výpočet tuto nerovnováhu neopraví. V lekci o `r render_glossary_term("nejistota", display = "nejistotě")` se vrátíme k odhadu z jednoho výběru; později budeme řešit také situace, kdy řádky nepředstavují nezávislé informační jednotky.
:::

## Vizualizace dat: nejdříve se podívejte

Samotný výpis `r length(vec_spanek_h)` hodnot se čte obtížně. Graf uspořádá
hodnoty podle jejich velikosti a dovolí nám vidět
`r render_glossary_term("rozdeleni", display = "rozdělení")`: kde se hodnoty
hromadí, jak široce jsou rozptýlené a zda některé leží stranou.

### Proč začínáme grafem?

Než začneme počítat souhrnná čísla, je dobrým obecným pravidlem **nejdříve
zobrazit jednotlivé hodnoty**. Graf může odhalit shluky, mezery, asymetrii nebo
hodnoty daleko od ostatních. Teprve potom dokážeme posoudit, který číselný popis
bude pro daná data smysluplný.

::: {.box-warning title="Nikdy nepracujte jen s čísly bez grafu"}

Samotný výpis hodnot se čte obtížně a souhrnné číslo část informace vždy skryje.
**Graf není ozdoba výsledku. Je to první kontrola toho, co se číselný popis
chystá zjednodušit.**
:::

```{r}
#| label: pripravit-zaklad-bodoveho-grafu
#| echo: false
#| message: false
#| warning: false
plot_spanek_body <-
  ggplot2::ggplot(
    data = data_spanek,
    mapping = ggplot2::aes(
      x = spanek_h,
      y = 1
    )
  ) +
  ggbeeswarm::geom_quasirandom(
    width = 0.38,
    orientation = "y",
    color = col_data,
    alpha = 0.75,
    size = 2.4
  ) +
  ggplot2::scale_x_continuous(
    breaks = seq(0, 20, by = 2)
  ) +
  ggplot2::coord_cartesian(
    xlim = c(0, 21),
    ylim = c(0.58, 1.42)
  ) +
  ggplot2::labs(
    x = "Celkový spánek za den (h)",
    y = NULL
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank()
  )
```

### Bodový graf

**Bodový graf (anglicky *dot plot*; zde uspořádaný jako *beeswarm plot*)**
zobrazuje každou hodnotu jako samostatný bod. Body jsou mírně posunuté nahoru
a dolů, aby se nepřekrývaly a lépe využily plochu grafu.

*Kolik druhů představuje jeden bod? Kde leží nejkratší a nejdelší doba spánku?*

::: {.panel-tabset}
#### Graf

```{r}
#| label: bodovy-graf-spanku
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.1
plot_spanek_body +
  ggplot2::labs(
    title = "Každý bod představuje jeden zastoupený druh"
  )
```

#### Kód v R

```{r}
#| label: bodovy-graf-kod
#| echo: true
#| eval: true
#| fig-height: 3.2
# Zobrazíme každou hodnotu jako jeden bod.
stripchart(
  x = vec_spanek_h,
  method = "jitter",
  jitter = 0.25,
  pch = 19,
  cex = 1.2,
  col = "#6B7280",
  xlab = "Celkový spánek za den (h)",
  main = "Bodový graf"
)
```
:::

Výhoda bodového grafu je úplnost: žádná hodnota nezmizí. Nevýhodou je, že u
velkých datových souborů se může mnoho bodů překrývat.

### Hodnoty seskupené do intervalů

`r render_glossary_term("histogram", display = "Histogram")` seskupuje
číselné hodnoty do navazujících intervalů neboli **košů** (anglicky *bins*).
Výška sloupce ukazuje `r render_glossary_term("cetnost", display = "četnost")`
hodnot v daném koši.

*Které rozmezí spánku obsahuje nejvíce druhů? Co už z histogramu nedokážete
vyčíst o jednotlivém druhu?*

::: {.panel-tabset}
#### Graf

```{r}
#| label: histogram-spanku
#| echo: false
#| message: false
#| warning: false
ggplot2::ggplot(
  data = data_spanek,
  mapping = ggplot2::aes(x = spanek_h)
) +
  ggplot2::geom_histogram(
    binwidth = 2,
    boundary = 0,
    fill = col_fill,
    color = "white"
  ) +
  ggplot2::scale_x_continuous(
    breaks = seq(0, 20, by = 2)
  ) +
  ggplot2::labs(
    x = "Celkový spánek za den (h)",
    y = "Počet druhů",
    title = "Histogram doby spánku",
    subtitle = "Jeden koš pokrývá dvě hodiny"
  )
```

```{=typst}
#pagebreak()
```

#### Kód v R

```{r}
#| label: histogram-spanku-kod
#| echo: true
#| eval: true
#| fig-height: 3.4
# Rozdělíme osu na intervaly široké dvě hodiny.
hist(
  x = vec_spanek_h,
  breaks = seq(
    from = 0,
    to = 22,
    by = 2
  ),
  col = "#D8C9E8",
  border = "white",
  xlab = "Celkový spánek za den (h)",
  ylab = "Počet druhů",
  main = "Histogram doby spánku"
)
```
:::

::: {.box-data collapse="true" title="Doplňující: jak volit šířku koše?"}

Volba šířky koše (anglicky *bin width*) mění míru detailu, ale nemění původní
hodnoty. Příliš úzké koše vytvoří zubatý graf; příliš široké koše mohou skrýt
důležitý tvar.

```{r}
#| label: porovnat-sirku-kose
#| echo: false
#| message: false
#| warning: false
hist_1 <- hist(
  vec_spanek_h,
  breaks = seq(0, 21, by = 1),
  plot = FALSE
)
hist_2 <- hist(
  vec_spanek_h,
  breaks = seq(0, 22, by = 2),
  plot = FALSE
)
hist_4 <- hist(
  vec_spanek_h,
  breaks = seq(0, 24, by = 4),
  plot = FALSE
)

data_kose <-
  dplyr::bind_rows(
    tibble::tibble(
      stred = hist_1$mids,
      pocet = hist_1$counts,
      sirka = 1,
      nastaveni = "Šířka koše = 1 h"
    ),
    tibble::tibble(
      stred = hist_2$mids,
      pocet = hist_2$counts,
      sirka = 2,
      nastaveni = "Šířka koše = 2 h"
    ),
    tibble::tibble(
      stred = hist_4$mids,
      pocet = hist_4$counts,
      sirka = 4,
      nastaveni = "Šířka koše = 4 h"
    )
  ) |>
  dplyr::mutate(
    nastaveni = factor(
      nastaveni,
      levels = c(
        "Šířka koše = 1 h",
        "Šířka koše = 2 h",
        "Šířka koše = 4 h"
      )
    )
  )

ggplot2::ggplot(
  data = data_kose,
  mapping = ggplot2::aes(
    x = stred,
    y = pocet,
    width = sirka
  )
) +
  ggplot2::geom_col(
    fill = col_fill,
    color = "white"
  ) +
  ggplot2::facet_wrap(~nastaveni) +
  ggplot2::scale_x_continuous(
    breaks = seq(0, 20, by = 4)
  ) +
  ggplot2::labs(
    x = "Celkový spánek za den (h)",
    y = "Počet druhů",
    title = "Stejná data, tři šířky koše"
  )
```

Praktický postup není hledat jedinou „správnou“ šířku. Vyzkoušejte několik
rozumných možností a ověřte, zda hlavní interpretace nezávisí na jednom
nastavení.
:::

### Graf hustoty

**Graf hustoty (anglicky *density plot*)** je vyhlazený pohled na tvar
číselných hodnot. Neukazuje počty druhů; osa *y* vyjadřuje hustotu. Křivka je
proto vhodná pro porovnávání tvaru, ale méně vhodná pro čtení konkrétních
četností.

*Kde má křivka vrchol? Odpovídá tato oblast nejvyšším sloupcům histogramu?*

::: {.panel-tabset}
#### Graf

```{r}
#| label: hustota-spanku
#| echo: false
#| message: false
#| warning: false
ggplot2::ggplot(
  data = data_spanek,
  mapping = ggplot2::aes(x = spanek_h)
) +
  ggplot2::geom_density(
    fill = col_fill,
    alpha = 0.55,
    color = col_median,
    linewidth = 1
  ) +
  ggplot2::scale_x_continuous(
    breaks = seq(0, 20, by = 2)
  ) +
  ggplot2::labs(
    x = "Celkový spánek za den (h)",
    y = "Hustota",
    title = "Graf hustoty doby spánku"
  )
```

#### Kód v R

```{r}
#| label: hustota-spanku-kod
#| echo: true
#| eval: true
#| fig-height: 3.4
# Odhadneme vyhlazenou hustotu hodnot.
hustota_spanku <-
  density(
    x = vec_spanek_h
  )

plot(
  x = hustota_spanku,
  xlab = "Celkový spánek za den (h)",
  ylab = "Hustota",
  main = "Graf hustoty doby spánku"
)
```
:::

### Tři pohledy na tutéž proměnnou

| Graf | Co zachovává | Co skrývá nebo mění |
|---|---|---|
| Bodový graf (*dot/beeswarm plot*) | každou jednotlivou hodnotu | při velkém počtu hodnot může být přeplněný |
| Histogram (*histogram*) | četnosti v intervalech a celkový tvar | přesné hodnoty; vzhled závisí na šířce koše |
| Graf hustoty (*density plot*) | hladký tvar rozdělení | konkrétní počty a jednotlivé hodnoty |

Žádný z těchto grafů není automaticky nejlepší. Vybíráme podle otázky a podle
toho, co potřebujeme čtenáři ukázat.

## Deskriptivní statistiky: čísla, která patří ke grafu

Graf ukazuje celý tvar dat. Někdy ale potřebujeme také několik
**srovnatelných čísel**: například do tabulky výsledků nebo do jedné věty v
článku. **Deskriptivní statistiky** shrnou:
<!-- TODO: add slug deskriptivni-statistika to pojmy.yaml -->

- **polohu** hodnot: kde leží jejich střed nebo okraje;
- **`r render_glossary_term("variabilita", display = "variabilitu")`**: jak moc
  se hodnoty liší.

Souhrnné číslo nikdy nenahrazuje graf. Čteme je společně.

### Malý skutečný příklad

Pro ruční výpočty použijeme devět známých druhů z `msleep`. Každý řádek stále
představuje druh a hodnotou je celkový spánek za den v hodinách.

```{r}
#| label: pripravit-maly-priklad-spanku
#| echo: false
#| message: false
#| warning: false
data_maly_spanek <-
  data_spanek |>
  dplyr::filter(
    druh %in% c(
      "Rabbit",
      "Domestic cat",
      "Dog",
      "Chimpanzee",
      "Sheep",
      "Human",
      "Pig",
      "Horse",
      "Cow"
    )
  ) |>
  dplyr::mutate(
    druh_cz = dplyr::recode(
      druh,
      "Rabbit" = "králík",
      "Domestic cat" = "kočka domácí",
      "Dog" = "pes",
      "Chimpanzee" = "šimpanz",
      "Sheep" = "ovce",
      "Human" = "člověk",
      "Pig" = "prase",
      "Horse" = "kůň",
      "Cow" = "kráva"
    )
  ) |>
  dplyr::arrange(spanek_h)

vec_maly_spanek <- data_maly_spanek[["spanek_h"]]
n_maly <- length(vec_maly_spanek)
minimum_maly <- min(vec_maly_spanek)
maximum_maly <- max(vec_maly_spanek)
q1_maly <- quantile(vec_maly_spanek, probs = 0.25, names = FALSE)
median_maly <- median(vec_maly_spanek)
q3_maly <- quantile(vec_maly_spanek, probs = 0.75, names = FALSE)
iqr_maly <- IQR(vec_maly_spanek)
prumer_maly <- mean(vec_maly_spanek)

txt_hodnoty_maly <-
  formatC(
    vec_maly_spanek,
    format = "fg",
    digits = 5,
    decimal.mark = ",",
    drop0trailing = TRUE
  )
txt_soucet_maly <-
  formatC(
    sum(vec_maly_spanek),
    format = "f",
    digits = 1,
    decimal.mark = ","
  )
txt_prumer_maly <-
  formatC(
    prumer_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_median_maly <-
  formatC(
    median_maly,
    format = "f",
    digits = 1,
    decimal.mark = ","
  )
txt_q1_maly <-
  formatC(
    q1_maly,
    format = "f",
    digits = 1,
    decimal.mark = ","
  )
txt_q3_maly <-
  formatC(
    q3_maly,
    format = "f",
    digits = 1,
    decimal.mark = ","
  )
txt_iqr_maly <-
  formatC(
    iqr_maly,
    format = "f",
    digits = 1,
    decimal.mark = ","
  )

math_hodnoty_maly <-
  stringr::str_replace_all(
    txt_hodnoty_maly,
    ",",
    "{,}"
  )
math_soucet_maly <-
  stringr::str_replace_all(
    txt_soucet_maly,
    ",",
    "{,}"
  )
math_prumer_maly <-
  stringr::str_replace_all(
    txt_prumer_maly,
    ",",
    "{,}"
  )
math_median_maly <-
  stringr::str_replace_all(
    txt_median_maly,
    ",",
    "{,}"
  )
math_q1_maly <-
  stringr::str_replace_all(
    txt_q1_maly,
    ",",
    "{,}"
  )
math_q3_maly <-
  stringr::str_replace_all(
    txt_q3_maly,
    ",",
    "{,}"
  )
math_iqr_maly <-
  stringr::str_replace_all(
    txt_iqr_maly,
    ",",
    "{,}"
  )
```

```{r}
#| label: tabulka-maleho-prikladu-spanku
#| echo: false
#| message: false
#| warning: false
data_maly_spanek |>
  dplyr::transmute(
    `Druh` = druh_cz,
    `Původní název (name)` = druh,
    `Spánek za den (h)` = spanek_h
  ) |>
  knitr::kable(
    align = c("l", "l", "r")
  )
```

Hodnoty jsou v tabulce seřazené od nejmenší po největší. Díky tomu můžeme
sledovat, odkud se každé další číslo bere.

### Minimum a maximum

**Minimum** je nejmenší pozorovaná hodnota a **maximum** největší. V malém
příkladu je minimum `r minimum_maly` h a maximum `r maximum_maly` h.

```{r}
#| label: minimum-maximum-v-r
#| echo: true
#| eval: true
# Nejkratší pozorovaná doba spánku.
min(vec_maly_spanek)

# Nejdelší pozorovaná doba spánku.
max(vec_maly_spanek)
```

Na grafu jsou to levý a pravý okraj pozorovaných hodnot.

::: {.panel-tabset}
#### Minimum

```{r}
#| label: minimum-na-grafu
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
plot_spanek_body +
  ggplot2::geom_vline(
    xintercept = min(vec_spanek_h),
    color = col_mean,
    linetype = "dashed",
    linewidth = 1.2
  ) +
  ggplot2::labs(
    title = paste0(
      "Minimum = ",
      formatC(
        min(vec_spanek_h),
        format = "f",
        digits = 1,
        decimal.mark = ","
      ),
      " h"
    )
  )
```

#### Maximum

```{r}
#| label: maximum-na-grafu
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
plot_spanek_body +
  ggplot2::geom_vline(
    xintercept = max(vec_spanek_h),
    color = col_mean,
    linetype = "dashed",
    linewidth = 1.2
  ) +
  ggplot2::labs(
    title = paste0(
      "Maximum = ",
      formatC(
        max(vec_spanek_h),
        format = "f",
        digits = 1,
        decimal.mark = ","
      ),
      " h"
    )
  )
```
:::

Minimum a maximum popisují pozorovaný rozsah, ale silně závisí na jediném
nejkrajnějším řádku.

### Aritmetický průměr

`r render_glossary_term("prumer", display = "Aritmetický průměr")` (anglicky
*mean*) získáme tak, že sečteme všechny hodnoty a součet vydělíme jejich počtem.

Nejdříve slovy:

$$
\text{průměrná doba spánku}
=
\frac{\text{součet dob spánku}}{\text{počet druhů}}
$$

V malém příkladu dosadíme všechny hodnoty z tabulky:

$$
\begin{align}
\text{průměrná doba spánku}
&=
\frac{`r paste(math_hodnoty_maly, collapse = " + ")`}{`r n_maly`}
\\
&=
\frac{`r math_soucet_maly`}{`r n_maly`}
\\
&=
`r math_prumer_maly`\ \text{h}
\end{align}
$$

Obecný zápis je:

$$
\overline{x}
=
\frac{1}{n}
\sum_{i=1}^{n}x_i
$$

Zde:

- $x_i$ je hodnota $i$-tého pozorování;
- $n$ je počet pozorování;
- $\sum$ znamená součet všech hodnot;
- $\overline{x}$ je průměr.

```{r}
#| label: prumer-v-r
#| echo: true
#| eval: true
# Průhledný výpočet: součet dělený počtem.
sum(vec_maly_spanek) / length(vec_maly_spanek)

# Stejný výsledek jednou funkcí.
mean(vec_maly_spanek)
```

```{r}
#| label: prumer-na-grafu
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
plot_spanek_body +
  ggplot2::geom_vline(
    xintercept = mean(vec_spanek_h),
    color = col_mean,
    linetype = "dashed",
    linewidth = 1.4
  ) +
  ggplot2::labs(
    title = paste0(
      "Průměr = ",
      formatC(
        mean(vec_spanek_h),
        format = "f",
        digits = 2,
        decimal.mark = ","
      ),
      " h"
    ),
    subtitle = "Přerušovaná čára označuje aritmetický průměr"
  )
```

Každá hodnota aritmetický průměr ovlivňuje. Proto se průměr posouvá směrem k velmi vzdáleným hodnotám.

### Prostřední hodnota seřazených dat

`r render_glossary_term("median", display = "Medián")` (anglicky *median*) je
prostřední hodnota seřazených dat. Polovina hodnot leží nejvýše na jeho úrovni
a polovina nejméně na jeho úrovni.

Nejdříve vztah zapíšeme pouze slovy:

$$
\text{medián doby spánku}
=
\text{prostřední hodnota seřazených dob spánku}
$$

V malém příkladu máme lichý počet hodnot. Prostřední je pátá:

$$
`r paste(math_hodnoty_maly[1:4], collapse = ",\\ ")`,
\ \boxed{`r math_median_maly`},
\ `r paste(math_hodnoty_maly[6:9], collapse = ",\\ ")`
$$

Teprve nyní zápis zobecníme. Pro lichý počet $n$ je medián hodnotou na pozici:

$$
\widetilde{x}
=
x_{\left(\frac{n+1}{2}\right)}
$$

Zde:

- $x$ označuje sledovanou číselnou proměnnou;
- $x_{(i)}$ označuje $i$-tou hodnotu po seřazení;
- $n$ je počet hodnot;
- $\widetilde{x}$ je medián.

```{r}
#| label: median-v-r
#| echo: true
#| eval: true
median(vec_maly_spanek)
```

```{r}
#| label: median-na-grafu
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
plot_spanek_body +
  ggplot2::geom_vline(
    xintercept = median(vec_spanek_h),
    color = col_median,
    linewidth = 1.4
  ) +
  ggplot2::labs(
    title = paste0(
      "Medián = ",
      formatC(
        median(vec_spanek_h),
        format = "f",
        digits = 1,
        decimal.mark = ","
      ),
      " h"
    ),
    subtitle = "Čára rozděluje seřazené druhy na dvě poloviny"
  )
```

### Průměr a medián: návrat k titulku

Nyní máme oba nástroje, které vytvořily úvodní titulky. Podívejme se na
hmotnosti všech zastoupených druhů.

```{r}
#| label: pripravit-hmotnost-pro-detektivku
#| echo: false
#| message: false
#| warning: false
data_hmotnost <-
  data_savci |>
  tidyr::drop_na(hmotnost_kg)

vec_hmotnost_kg <- data_hmotnost[["hmotnost_kg"]]
prumer_hmotnost <- mean(vec_hmotnost_kg)
median_hmotnost <- median(vec_hmotnost_kg)
```

::: {.panel-tabset}
#### Původní osa

```{r}
#| label: hmotnost-prumer-median-puvodni
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
ggplot2::ggplot(
  data = data_hmotnost,
  mapping = ggplot2::aes(
    x = hmotnost_kg,
    y = 1
  )
) +
  ggbeeswarm::geom_beeswarm(
    cex = 0.8,
    color = col_data,
    alpha = 0.7,
    size = 2.1
  ) +
  ggplot2::geom_vline(
    xintercept = prumer_hmotnost,
    color = col_mean,
    linetype = "dashed",
    linewidth = 1.2
  ) +
  ggplot2::geom_vline(
    xintercept = median_hmotnost,
    color = col_median,
    linewidth = 1.2
  ) +
  ggplot2::coord_cartesian(ylim = c(0.8, 1.2)) +
  ggplot2::labs(
    x = "Tělesná hmotnost (body weight; kg)",
    y = NULL,
    title = "Několik velmi těžkých druhů roztahuje osu",
    subtitle = "Oranžově průměr, fialově medián"
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank()
  )
```

#### Přiblížení pomocí logaritmické osy

```{r}
#| label: hmotnost-prumer-median-log
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
ggplot2::ggplot(
  data = data_hmotnost,
  mapping = ggplot2::aes(
    x = hmotnost_kg,
    y = 1
  )
) +
  ggbeeswarm::geom_beeswarm(
    cex = 0.8,
    color = col_data,
    alpha = 0.7,
    size = 2.1
  ) +
  ggplot2::geom_vline(
    xintercept = prumer_hmotnost,
    color = col_mean,
    linetype = "dashed",
    linewidth = 1.2
  ) +
  ggplot2::geom_vline(
    xintercept = median_hmotnost,
    color = col_median,
    linewidth = 1.2
  ) +
  ggplot2::scale_x_log10(
    breaks = c(0.01, 0.1, 1, 10, 100, 1000),
    labels = c("0,01", "0,1", "1", "10", "100", "1000")
  ) +
  ggplot2::coord_cartesian(ylim = c(0.8, 1.2)) +
  ggplot2::labs(
    x = "Tělesná hmotnost (body weight; kg; logaritmická osa)",
    y = NULL,
    title = "Logaritmická osa zpřístupní lehké i těžké druhy",
    subtitle = "Výpočty zůstávají v původních kilogramech"
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank()
  )
```
:::

Na původní ose vidíme, že většina druhů leží blízko nuly ve srovnání s několika
velmi těžkými druhy. Logaritmická osa pouze mění rozestupy na grafu, aby byly
body čitelné; průměr i medián jsou stále vypočtené z kilogramů.

- Průměr hmotnosti je
  **`r formatC(prumer_hmotnost, format = "f", digits = 0, decimal.mark = ",")`
  kg**.
- Medián hmotnosti je
  **`r formatC(median_hmotnost, format = "f", digits = 2, decimal.mark = ",")`
  kg**.

Obě čísla jsou vypočtena správně. Průměr ale silně posunulo několik velmi
těžkých druhů. Medián lépe popisuje prostřední řádek této výrazně asymetrické
tabulky.

::: {.box-result title="Vyřešení úvodního hlasování"}

Nejpřesnější odpověď byla **C) Obě čísla mohou být vypočtena správně.**
Správný výpočet však ještě nezaručuje poctivý titulek. Musíme také uvést, jaké
shrnutí jsme použili, jak vypadá graf a co představuje jeden řádek.
:::

::: {.box-data collapse="true" title="Doplňující: kdy může být průměr užitečnější?"}

`r render_glossary_term("prumer", display = "Průměr")` je přirozený pro
přibližně symetrická číselná data bez mimořádně
vzdálených hodnot a je základním stavebním kamenem mnoha statistických modelů.
`r render_glossary_term("median", display = "Medián")` je odolnější vůči
`r render_glossary_term("odlehla-pozorovani", display = "odlehlým pozorováním")`
a často lépe popisuje střed silně asymetrických dat. Volba není soutěž mezi
„dobrou“ a „špatnou“ statistikou; musí odpovídat grafu a otázce.
:::

### Percentily a kvartily

**Percentil (anglicky *percentile*)** je hodnota, pod níž leží určitý podíl
seřazených dat. Několik percentilů má vlastní názvy;
`r render_glossary_term("kvantil", display = "kvartily")` dělí seřazená data na
čtyři části:

- 0. percentil je minimum;
- 25. percentil je dolní kvartil Q1;
- 50. percentil je medián;
- 75. percentil je horní kvartil Q3;
- 100. percentil je maximum.

```{r}
#| label: percentily-v-r
#| echo: true
#| eval: true
quantile(
  x = vec_maly_spanek,
  probs = c(0, 0.25, 0.50, 0.75, 1)
)
```

*Najděte v následujícím grafu prostřední čáru a pásmo mezi Q1 a Q3. Kolik
hodnot by přibližně mělo ležet uvnitř pásma?*

```{r}
#| label: kvartily-na-grafu
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
q_spanek <-
  quantile(
    vec_spanek_h,
    probs = c(0.25, 0.50, 0.75),
    names = FALSE
  )

plot_spanek_body +
  ggplot2::annotate(
    geom = "rect",
    xmin = q_spanek[[1]],
    xmax = q_spanek[[3]],
    ymin = -Inf,
    ymax = Inf,
    fill = col_fill,
    alpha = 0.45
  ) +
  ggplot2::geom_vline(
    xintercept = q_spanek,
    color = c(col_data, col_median, col_data),
    linetype = c("dashed", "solid", "dashed"),
    linewidth = c(0.9, 1.4, 0.9)
  ) +
  ggplot2::labs(
    title = "Q1, medián a Q3 rozdělují seřazené hodnoty",
    subtitle = "Stínované pásmo obsahuje prostřední polovinu druhů"
  )
```

::: {.box-data collapse="true" title="Doplňující: proč kvartil nemusí být přímo v datech?"}

U malého souboru může požadovaná procentní pozice ležet mezi dvěma
pozorovanými hodnotami. R pak podle zvolené metody provede interpolaci. Proto
kvartil nemusí být přesně jednou z hodnot v tabulce. Funkce `quantile()` nabízí
více metod pomocí argumentu `type`; pro tento úvod ponecháváme výchozí
nastavení.
:::

### Prostřední polovina hodnot

Medián popisuje polohu středu, nikoli šířku dat.
`r render_glossary_term("iqr", display = "Mezikvartilové rozpětí (IQR)")`
(anglicky *interquartile range*) je vzdálenost mezi horním a dolním kvartilem.

Nejdříve slovy:

$$
\text{mezikvartilové rozpětí doby spánku}
=
\text{horní kvartil doby spánku}
-
\text{dolní kvartil doby spánku}
$$

V malém příkladu nejprve znovu ukážeme všech devět seřazených hodnot. Dolní a
horní kvartil jsou zde třetí a sedmá hodnota:

$$
`r paste(math_hodnoty_maly[1:2], collapse = ",\\ ")`,
\ \boxed{`r math_q1_maly`}_{Q_1},
\ `r paste(math_hodnoty_maly[4:6], collapse = ",\\ ")`,
\ \boxed{`r math_q3_maly`}_{Q_3},
\ `r paste(math_hodnoty_maly[8:9], collapse = ",\\ ")`
$$

Teprve potom odečteme jejich hodnoty:

$$
\begin{align}
\text{IQR}
&=
`r math_q3_maly`
-
`r math_q1_maly`
\\
&=
`r math_iqr_maly`\ \text{h}
\end{align}
$$

Obecný zápis je:

$$
\text{IQR}
=
Q_3-Q_1
$$

Zde $Q_1$ označuje dolní kvartil a $Q_3$ horní kvartil. IQR popisuje rozsah
prostřední poloviny hodnot.

```{r}
#| label: iqr-v-r
#| echo: true
#| eval: true
quantile(
  x = vec_maly_spanek,
  probs = c(0.25, 0.75)
)

IQR(vec_maly_spanek)
```

```{r}
#| label: iqr-na-grafu
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
q1_spanek <- quantile(vec_spanek_h, probs = 0.25, names = FALSE)
q3_spanek <- quantile(vec_spanek_h, probs = 0.75, names = FALSE)

plot_spanek_body +
  ggplot2::annotate(
    geom = "rect",
    xmin = q1_spanek,
    xmax = q3_spanek,
    ymin = -Inf,
    ymax = Inf,
    fill = col_fill,
    alpha = 0.5
  ) +
  ggplot2::geom_vline(
    xintercept = c(q1_spanek, q3_spanek),
    color = col_data,
    linetype = "dashed",
    linewidth = 1
  ) +
  ggplot2::labs(
    title = paste0(
      "IQR = ",
      formatC(
        IQR(vec_spanek_h),
        format = "f",
        digits = 1,
        decimal.mark = ","
      ),
      " h"
    ),
    subtitle = "Stínované pásmo = prostřední polovina druhů"
  )
```

### Od středu k variabilitě

Nyní známe minimum, maximum, průměr, medián, kvartily a IQR. Následující dva
malé soubory jsou **záměrně sestavené didaktické příklady**, nikoli další
pozorování z `msleep`. Jejich průměr je stejný:

```{r}
#| label: stejny-prumer-vypocet
#| echo: true
#| eval: true
vec_spanek_a <-
  c(8, 9, 9, 10, 10, 10, 11, 11, 12)

vec_spanek_b <-
  c(6, 6, 8, 8, 10, 12, 12, 14, 14)

mean(vec_spanek_a)
mean(vec_spanek_b)
```

```{r}
#| label: pripravit-stejny-prumer
#| echo: false
#| message: false
#| warning: false
data_stejny_prumer <-
  tibble::tibble(
    spanek_h = c(
      vec_spanek_a,
      vec_spanek_b
    ),
    skupina = rep(c("Soubor A", "Soubor B"), each = 9)
  )

plot_stejny_prumer <-
  ggplot2::ggplot(
    data = data_stejny_prumer,
    mapping = ggplot2::aes(
      x = spanek_h,
      y = 1
    )
  ) +
  ggbeeswarm::geom_beeswarm(
    mapping = ggplot2::aes(color = skupina),
    cex = 1,
    size = 4
  ) +
  ggplot2::facet_wrap(~skupina) +
  ggplot2::geom_vline(
    xintercept = mean(vec_spanek_a),
    color = col_mean,
    linetype = "dashed",
    linewidth = 1
  ) +
  ggplot2::scale_color_manual(
    values = c("Soubor A" = col_median, "Soubor B" = col_mean)
  ) +
  ggplot2::scale_x_continuous(breaks = 6:14) +
  ggplot2::coord_cartesian(ylim = c(0.9, 1.1)) +
  ggplot2::labs(
    x = "Celkový spánek za den (h)",
    y = NULL,
    title = "Stejný průměr, jiný tvar hodnot",
    subtitle = paste0(
      "Přerušovaná čára označuje průměr ",
      formatC(
        mean(vec_spanek_a),
        format = "f",
        digits = 0,
        decimal.mark = ","
      ),
      " hodin"
    )
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank(),
    legend.position = "none"
  )
```

*Nejdříve graf sami popište: kde leží hodnoty a v čem se oba soubory liší?*

```{r}
#| label: navrat-ke-stejnemu-prumeru
#| echo: false
#| message: false
#| warning: false
#| fig-height: 3
plot_stejny_prumer
```

Soubor A je soustředěný kolem
`r formatC(mean(vec_spanek_a), format = "f", digits = 0, decimal.mark = ",")`
hodin. Soubor B má více hodnot na obou okrajích a méně hodnot poblíž středu.
Stejný průměr tuto odlišnost skryl.

::: {.box-question title="Potřebujeme ještě jedno číslo"}
Jak bychom jedním číslem popsali vzdálenosti **všech hodnot od průměru**?
Odpověď budeme hledat v následující části.
:::

### Jak daleko hodnoty leží od středu

Průměr popsal střed. Nyní potřebujeme říci, jak moc jsou hodnoty **rozptýlené
kolem průměru**. Začneme vzdáleností každé hodnoty od průměru.

Nejdříve slovy:

$$
\text{odchylka doby spánku druhu}
=
\text{doba spánku druhu}
-
\text{průměrná doba spánku}
$$

```{r}
#| label: pripravit-odchylky-spanku
#| echo: false
#| message: false
#| warning: false
odchylky_maly <- vec_maly_spanek - prumer_maly
ctverce_odchylek_maly <- odchylky_maly^2
soucet_ctvercu_maly <- sum(ctverce_odchylek_maly)
rozptyl_maly <- soucet_ctvercu_maly / (n_maly - 1)
sd_maly <- sqrt(rozptyl_maly)

data_odchylky_maly <-
  data_maly_spanek |>
  dplyr::mutate(
    prumer = prumer_maly,
    odchylka = spanek_h - prumer_maly,
    ctverec_odchylky = odchylka^2,
    poloha = dplyr::if_else(
      odchylka < 0,
      "pod průměrem",
      "nad průměrem"
    ),
    druh_cz = forcats::fct_reorder(druh_cz, spanek_h)
  )

index_kocka_maly <- which(data_odchylky_maly$druh_cz == "kočka domácí")
hodnota_kocka_maly <- data_odchylky_maly$spanek_h[[index_kocka_maly]]
odchylka_kocka_maly <- data_odchylky_maly$odchylka[[index_kocka_maly]]
ctverec_kocka_maly <-
  data_odchylky_maly$ctverec_odchylky[[index_kocka_maly]]

txt_hodnota_kocka_maly <-
  formatC(
    hodnota_kocka_maly,
    format = "f",
    digits = 1,
    decimal.mark = ","
  )
txt_odchylka_kocka_maly <-
  formatC(
    odchylka_kocka_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_ctverec_kocka_maly <-
  formatC(
    ctverec_kocka_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_soucet_odchylek_maly <-
  formatC(
    sum(odchylky_maly),
    format = "f",
    digits = 2,
    decimal.mark = ","
  )

txt_odchylky_maly <-
  formatC(
    odchylky_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_ctverce_maly <-
  formatC(
    ctverce_odchylek_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_soucet_ctvercu_maly <-
  formatC(
    soucet_ctvercu_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_rozptyl_maly <-
  formatC(
    rozptyl_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )
txt_sd_maly <-
  formatC(
    sd_maly,
    format = "f",
    digits = 2,
    decimal.mark = ","
  )

math_odchylky_maly <-
  stringr::str_replace_all(
    txt_odchylky_maly,
    ",",
    "{,}"
  )
math_ctverce_maly <-
  stringr::str_replace_all(
    txt_ctverce_maly,
    ",",
    "{,}"
  )
math_soucet_ctvercu_maly <-
  stringr::str_replace_all(
    txt_soucet_ctvercu_maly,
    ",",
    "{,}"
  )
math_rozptyl_maly <-
  stringr::str_replace_all(
    txt_rozptyl_maly,
    ",",
    "{,}"
  )
math_sd_maly <-
  stringr::str_replace_all(
    txt_sd_maly,
    ",",
    "{,}"
  )
```

Na grafu je odchylka vidět jako úsek od průměru k hodnotě každého druhu.
Fialové úseky vedou pod průměr, oranžové nad něj.

```{r}
#| label: odchylky-od-prumeru-graf
#| echo: false
#| message: false
#| warning: false
#| fig-height: 4.6
ggplot2::ggplot(
  data = data_odchylky_maly,
  mapping = ggplot2::aes(y = druh_cz)
) +
  ggplot2::geom_segment(
    mapping = ggplot2::aes(
      x = prumer,
      xend = spanek_h,
      yend = druh_cz,
      color = poloha
    ),
    linewidth = 2.4,
    alpha = 0.6
  ) +
  ggplot2::geom_vline(
    xintercept = prumer_maly,
    color = col_median,
    linewidth = 1.2
  ) +
  ggplot2::geom_point(
    mapping = ggplot2::aes(x = spanek_h),
    color = col_data,
    size = 3
  ) +
  ggplot2::scale_color_manual(
    values = c(
      "pod průměrem" = col_median,
      "nad průměrem" = col_mean
    )
  ) +
  ggplot2::labs(
    x = "Celkový spánek za den (h)",
    y = NULL,
    color = NULL,
    title = "Vzdálenosti jednotlivých hodnot od průměru"
  ) +
  ggplot2::theme(legend.position = "none")
```

::: {.box-data collapse="true" title="Extra: od odchylek k součtu čtverců, rozptylu a SD"}

Tabulka propojuje každou hodnotu s jejím místem v dalším výpočtu:

```{r}
#| label: tabulka-odchylek-spanku
#| echo: false
#| message: false
#| warning: false
data_maly_spanek |>
  dplyr::transmute(
    `Druh` = druh_cz,
    `Spánek (h)` = spanek_h,
    `Odchylka od průměru (h)` = round(odchylky_maly, 2),
    `Čtverec odchylky (h²)` = round(ctverce_odchylek_maly, 2)
  ) |>
  knitr::kable(
    align = c("l", "r", "r", "r")
  )
```

Například u kočky domácí dosadíme hodnotu z grafu a průměr:

$$
\begin{align}
\text{odchylka spánku kočky domácí}
&=
`r txt_hodnota_kocka_maly`
-
`r math_prumer_maly`
\\
&=
`r txt_odchylka_kocka_maly`\ \text{h}
\end{align}
$$

Obecný zápis odchylky je:

$$
e_i=x_i-\overline{x}
$$

Zde $e_i$ označuje odchylku $i$-té hodnoty od průměru. Kladné a záporné
odchylky se při prostém součtu vyruší: zde dávají po zaokrouhlení
`r txt_soucet_odchylek_maly` h. Proto je umocníme na druhou a sečteme. Výsledek
se nazývá **součet čtverců** (anglicky *sum of squares*, SS).

```{r}
#| label: ctverce-odchylek-graf
#| echo: false
#| message: false
#| warning: false
#| fig-height: 4.6
ggplot2::ggplot(
  data = data_odchylky_maly,
  mapping = ggplot2::aes(
    x = ctverec_odchylky,
    y = forcats::fct_reorder(druh_cz, ctverec_odchylky)
  )
) +
  ggplot2::geom_col(
    fill = col_mean,
    alpha = 0.78,
    width = 0.72
  ) +
  ggplot2::labs(
    x = "Čtverec odchylky (h²)",
    y = NULL,
    title = "Po umocnění jsou všechny příspěvky nezáporné"
  )
```

V tomto souboru přispívá k součtu čtverců nejvíce **kočka domácí**:
její čtverec odchylky je `r txt_ctverec_kocka_maly` h². Nejde o chybu; kočka
jen leží ze všech devíti druhů nejdále od průměru.

$$
\begin{align}
\text{součet čtverců odchylek}
&=
`r paste(math_ctverce_maly, collapse = " + ")`
\\
&=
`r math_soucet_ctvercu_maly`\ \text{h}^2
\end{align}
$$

Obecně:

$$
\text{SS}
=
\sum_{i=1}^{n}
\left(x_i-\overline{x}\right)^2
$$

`r render_glossary_term("rozptyl", display = "Výběrový rozptyl")` (anglicky *sample variance*) získáme vydělením součtu čtverců počtem hodnot minus jedna. Když máme jedinou hodnotu, její průměr je ona sama a odchylka je vždy nula: o skutečné proměnlivosti tak nic nezjistíme. U dvou hodnot po určení průměru stačí znát jednu odchylku, protože druhá musí být opačná. Po odhadu průměru tedy zbývá o jednu nezávislou odchylku méně; tím si vysvětlíme dělitele `n - 1` bez formální definice stupňů volnosti.

Nejdříve slovy:

$$
\text{výběrový rozptyl doby spánku}
=
\frac{\text{součet čtverců odchylek}}{\text{počet druhů}-1}
$$

V malém příkladu:

$$
\begin{align}
\text{výběrový rozptyl doby spánku}
&=
\frac{`r math_soucet_ctvercu_maly`}{`r n_maly`-1}
\\
&=
\frac{`r math_soucet_ctvercu_maly`}{`r n_maly - 1`}
\\
&=
`r math_rozptyl_maly`\ \text{h}^2
\end{align}
$$

Obecně:

$$
s^2
=
\frac{1}{n-1}
\sum_{i=1}^{n}
\left(x_i-\overline{x}\right)^2
$$

Rozptyl má čtvercové jednotky, zde hodiny na druhou. Abychom se vrátili k
hodinám, vezmeme odmocninu. Tím získáme
`r render_glossary_term("smerodatna-odchylka", display = "směrodatnou odchylku (SD)")`
(anglicky *standard deviation*).

Nejdříve slovy:

$$
\text{směrodatná odchylka doby spánku}
=
\sqrt{\text{výběrový rozptyl doby spánku}}
$$

V malém příkladu:

$$
\begin{align}
\text{směrodatná odchylka doby spánku}
&=
\sqrt{`r math_rozptyl_maly`}
\\
&=
`r math_sd_maly`\ \text{h}
\end{align}
$$

Obecně:

$$
s=\sqrt{s^2}
$$

Zde $s^2$ označuje výběrový rozptyl a $s$ směrodatnou odchylku. SD má stejné
jednotky jako původní proměnná.

```{r}
#| label: rozptyl-sd-v-r
#| echo: true
#| eval: true
# Výběrový rozptyl v hodinách na druhou.
var(vec_maly_spanek)

# Směrodatná odchylka v hodinách.
sd(vec_maly_spanek)
```

:::

Směrodatná odchylka (SD) vyjadřuje, jak rozptýlené jsou hodnoty kolem průměru, ve stejných jednotkách jako původní měření. Pro doby spánku ji spočítáme v R pomocí `sd(vec_maly_spanek)`. Podrobný výpočet přes součet čtverců a rozptyl je v rámečku Extra.

::: {.box-data collapse="true" title="Doplňující: SD není standardní chyba"}

SD popisuje, jak se od sebe liší **pozorované hodnoty** — zde doby spánku jednotlivých zastoupených druhů. `r render_glossary_term("standardni-chyba", display = "Standardní chyba")` (SE) bude později popisovat něco jiného: jak přesný je **`r render_glossary_term("odhad", display = "odhad")`**, například odhad průměru nebo `r render_glossary_term("sklon", display = "sklonu")` modelu.

Velká SD tedy neznamená automaticky chybný výpočet a malá SD neznamená automaticky přesný odhad pro celou populaci. Zatím stačí držet dvě otázky odděleně: **jak rozdílná jsou pozorování?** odpovídá SD; **jak přesný je náš odhad?** začne odpovídat SE v lekci o nejistotě odhadu.
:::

### SD jako vzdálenost na grafu

Na grafu můžeme kolem průměru vyznačit vzdálenost jedné SD na obě strany.
Pásmo není automatickým pravidlem, kolik bodů „musí“ obsahovat. Ukazuje měřítko
rozptýlení hodnot kolem průměru.

```{r}
#| label: sd-jako-pasmo
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
prumer_spanek <- mean(vec_spanek_h)
sd_spanek <- sd(vec_spanek_h)

plot_spanek_body +
  ggplot2::annotate(
    geom = "rect",
    xmin = prumer_spanek - sd_spanek,
    xmax = prumer_spanek + sd_spanek,
    ymin = -Inf,
    ymax = Inf,
    fill = col_mean,
    alpha = 0.16
  ) +
  ggplot2::geom_vline(
    xintercept = prumer_spanek,
    color = col_mean,
    linetype = "dashed",
    linewidth = 1.3
  ) +
  ggplot2::labs(
    title = paste0(
      "Průměr = ",
      formatC(
        prumer_spanek,
        format = "f",
        digits = 2,
        decimal.mark = ","
      ),
      " h; SD = ",
      formatC(
        sd_spanek,
        format = "f",
        digits = 2,
        decimal.mark = ","
      ),
      " h"
    ),
    subtitle = "Stínované pásmo sahá jednu SD na každou stranu od průměru"
  )
```

### Stejná průměrná mzda, jiná SD

Význam SD si lze snadno představit u měsíčních mezd. Následující dvě firmy jsou
**smyšlený příklad**: v obou je průměrná mzda 50 tisíc Kč, ale jednotlivé mzdy
se kolem stejného průměru rozkládají jinak.

```{r}
#| label: porovnat-sd-stejne-mzdy
#| echo: false
#| message: false
#| warning: false
#| fig-height: 3.4
set.seed(20260727)

vec_mzda_firma_a <-
  as.numeric(scale(stats::rnorm(n = 240))) * 3 + 50
vec_mzda_firma_b <-
  as.numeric(scale(stats::rnorm(n = 240))) * 12 + 50

data_mzdy_sd <-
  tibble::tibble(
    firma = rep(
      c(
        "Firma A: SD = 3 tis. Kč",
        "Firma B: SD = 12 tis. Kč"
      ),
      each = 240
    ),
    mzda_tis_kc = c(vec_mzda_firma_a, vec_mzda_firma_b)
  )

ggplot2::ggplot(
  data = data_mzdy_sd,
  mapping = ggplot2::aes(x = mzda_tis_kc)
) +
  ggplot2::geom_histogram(
    binwidth = 3,
    boundary = 0,
    fill = col_fill,
    color = "white"
  ) +
  ggplot2::geom_vline(
    xintercept = 50,
    color = col_mean,
    linewidth = 1.2
  ) +
  ggplot2::facet_wrap(~firma, ncol = 2) +
  ggplot2::labs(
    x = "Měsíční mzda (tis. Kč)",
    y = "Počet zaměstnanců",
    title = "Stejný průměr 50 tisíc Kč, jiná šířka histogramu"
  )
```

Ve firmě A leží mzdy blíže průměru a SD je 3 tisíce Kč. Ve firmě B jsou mzdy
rozptýlenější a SD je 12 tisíc Kč. **Vyšší SD znamená větší typickou vzdálenost
hodnot od průměru**, nikoli automaticky vyšší nebo nižší mzdu.

::: {.box-data collapse="true" title="Doplňující: co může míra rozptýlení znamenat biologicky?"}

Představte si dvě populace ptáků se stejnou
`r render_glossary_term("prumer", display = "průměrnou")` délkou křídla. Jedna
má `r render_glossary_term("smerodatna-odchylka", display = "malou SD")`, druhá
velkou. První je z hlediska délky křídel uniformnější; druhá
`r render_glossary_term("variabilita", display = "variabilnější")`. Příčinou
mohou být například rozdílné podmínky prostředí,
smíšené věkové skupiny, pohlavní dimorfismus nebo chyba měření. SD sama příčinu
neodhalí, ale upozorní, že biologická variabilita stojí za další otázku.
:::

### Které dvojice souhrnů patří k sobě?

| Míra středu | Míra variability | Kdy je dvojice často užitečná |
|---|---|---|
| průměr (*mean*) | směrodatná odchylka (*standard deviation*) | přibližně symetrická číselná data bez výrazně vzdálených hodnot |
| medián (*median*) | IQR (*interquartile range*) | asymetrická číselná data nebo data s výrazně vzdálenými hodnotami |

Nejde o mechanické pravidlo. Nejprve vždy prohlédněte graf a zvažte biologický
význam.

## Statistiky jako vizualizace: stavíme graf ze souhrnů

Minimum, `r render_glossary_term("kvantil", display = "kvartily")`,
`r render_glossary_term("median", display = "medián")` a
`r render_glossary_term("iqr", display = "IQR")` již známe. Nyní z nich sestavíme
`r render_glossary_term("boxplot", display = "krabicový graf (boxplot)")`
krok za krokem, aby žádná jeho část nebyla záhadným symbolem. Pokračujeme s
tělesnou hmotností: správně vypočtený titulek tak můžeme doplnit grafem, který
ukáže celé `r render_glossary_term("rozdeleni", display = "rozdělení")`
zastoupených druhů.

```{r}
#| label: pripravit-konstrukci-boxplotu
#| echo: false
#| message: false
#| warning: false
stat_boxplot_hmotnost <- boxplot.stats(vec_hmotnost_kg)
q1_hmotnost <- stat_boxplot_hmotnost$stats[[2]]
q3_hmotnost <- stat_boxplot_hmotnost$stats[[4]]
iqr_hmotnost <- q3_hmotnost - q1_hmotnost
hranice_dolni_hmotnost <- q1_hmotnost - 1.5 * iqr_hmotnost
hranice_horni_hmotnost <- q3_hmotnost + 1.5 * iqr_hmotnost
vous_dolni_hmotnost <- stat_boxplot_hmotnost$stats[[1]]
vous_horni_hmotnost <- stat_boxplot_hmotnost$stats[[5]]
vec_odlehle_hmotnost <- stat_boxplot_hmotnost$out

data_boxplot_hmotnost <-
  tibble::tibble(
    skupina = "",
    vous_dolni = vous_dolni_hmotnost,
    q1 = q1_hmotnost,
    median = median_hmotnost,
    q3 = q3_hmotnost,
    vous_horni = vous_horni_hmotnost
  )

math_q1_hmotnost <-
  q1_hmotnost |>
    formatC(
      format = "fg",
      digits = 4,
      decimal.mark = ",",
      drop0trailing = TRUE
    ) |>
    stringr::str_replace_all(",", "{,}")

math_q3_hmotnost <-
  q3_hmotnost |>
    formatC(
      format = "fg",
      digits = 4,
      decimal.mark = ",",
      drop0trailing = TRUE
    ) |>
    stringr::str_replace_all(",", "{,}")

math_iqr_hmotnost <-
  iqr_hmotnost |>
    formatC(
      format = "fg",
      digits = 4,
      decimal.mark = ",",
      drop0trailing = TRUE
    ) |>
    stringr::str_replace_all(",", "{,}")

math_hranice_dolni_hmotnost <-
  hranice_dolni_hmotnost |>
    formatC(
      format = "fg",
      digits = 4,
      decimal.mark = ",",
      drop0trailing = TRUE
    ) |>
    stringr::str_replace_all(",", "{,}")

math_hranice_horni_hmotnost <-
  hranice_horni_hmotnost |>
    formatC(
      format = "fg",
      digits = 4,
      decimal.mark = ",",
      drop0trailing = TRUE
    ) |>
    stringr::str_replace_all(",", "{,}")

plot_hmotnost_body_box <-
  ggplot2::ggplot(
    data = data_hmotnost,
    mapping = ggplot2::aes(
      x = hmotnost_kg,
      y = 1
    )
  ) +
  ggbeeswarm::geom_beeswarm(
    cex = 0.8,
    color = col_data,
    alpha = 0.7,
    size = 2.1
  ) +
  ggplot2::scale_x_log10(
    breaks = c(0.01, 0.1, 1, 10, 100, 1000),
    labels = c("0,01", "0,1", "1", "10", "100", "1000")
  ) +
  ggplot2::coord_cartesian(ylim = c(0.8, 1.2)) +
  ggplot2::labs(
    x = "Tělesná hmotnost (kg; logaritmická osa)",
    y = NULL
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank()
  )
```

### Krok 1: jednotlivé hodnoty a medián

Začneme bodovým grafem a přidáme čáru na pozici mediánu. Každý bod stále
vidíme.

```{r}
#| label: boxplot-krok-median
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
plot_hmotnost_body_box +
  ggplot2::geom_vline(
    xintercept = median_hmotnost,
    color = col_median,
    linewidth = 1.5
  ) +
  ggplot2::labs(
    title = "Krok 1: medián rozděluje seřazené hodnoty na poloviny"
  )
```

### Krok 2: krabice je IQR

Obdélník od Q1 do Q3 obsahuje prostřední polovinu hodnot. Jeho šířka je IQR.

```{r}
#| label: boxplot-krok-krabice
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
plot_hmotnost_body_box +
  ggplot2::annotate(
    geom = "rect",
    xmin = q1_hmotnost,
    xmax = q3_hmotnost,
    ymin = 0.83,
    ymax = 1.17,
    fill = col_fill,
    color = col_data,
    alpha = 0.65,
    linewidth = 0.9
  ) +
  ggplot2::geom_vline(
    xintercept = median_hmotnost,
    color = col_median,
    linewidth = 1.5
  ) +
  ggplot2::labs(
    title = "Krok 2: krabice sahá od Q1 do Q3",
    subtitle = "Její šířka odpovídá IQR"
  )
```

### Krok 3: vousy a body za nimi

Od hran krabice odměříme vzdálenost 1,5násobku IQR. Vous končí na nejkrajnější
skutečně pozorované hodnotě, která ještě leží uvnitř této hranice. Hodnoty za
vousy se vykreslí samostatně jako možná
`r render_glossary_term("odlehla-pozorovani", display = "odlehlá pozorování")`.
V předchozích krocích byly všechny původní body šedé; od tohoto kroku
zobrazujeme body za hranicemi samostatně šedě. Chceme je vidět, ale nejsou
automaticky hlavním sdělením grafu.

```{r}
#| label: boxplot-krok-vousy
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
ggplot2::ggplot() +
  ggplot2::annotate(
    geom = "rect",
    xmin = q1_hmotnost,
    xmax = q3_hmotnost,
    ymin = 0.83,
    ymax = 1.17,
    fill = col_fill,
    color = col_data,
    alpha = 0.65,
    linewidth = 0.9
  ) +
  ggplot2::annotate(
    geom = "segment",
    x = vous_dolni_hmotnost,
    xend = q1_hmotnost,
    y = 1,
    yend = 1,
    color = col_data,
    linewidth = 1
  ) +
  ggplot2::annotate(
    geom = "segment",
    x = q3_hmotnost,
    xend = vous_horni_hmotnost,
    y = 1,
    yend = 1,
    color = col_data,
    linewidth = 1
  ) +
  ggplot2::annotate(
    geom = "segment",
    x = c(vous_dolni_hmotnost, vous_horni_hmotnost),
    xend = c(vous_dolni_hmotnost, vous_horni_hmotnost),
    y = 0.9,
    yend = 1.1,
    color = col_data,
    linewidth = 1
  ) +
  ggplot2::annotate(
    geom = "segment",
    x = median_hmotnost,
    xend = median_hmotnost,
    y = 0.83,
    yend = 1.17,
    color = col_median,
    linewidth = 1.5
  ) +
  ggplot2::geom_point(
    data = tibble::tibble(
      hmotnost_kg = vec_odlehle_hmotnost,
      y = 1
    ),
    mapping = ggplot2::aes(
      x = hmotnost_kg,
      y = y
    ),
    color = col_data,
    fill = col_data,
    shape = 21,
    size = 3,
    stroke = 1.2
  ) +
  ggplot2::scale_x_log10(
    breaks = c(0.01, 0.1, 1, 10, 100, 1000),
    labels = c("0,01", "0,1", "1", "10", "100", "1000")
  ) +
  ggplot2::coord_cartesian(
    ylim = c(0.75, 1.25)
  ) +
  ggplot2::labs(
    x = "Tělesná hmotnost (kg; logaritmická osa)",
    y = NULL,
    title = "Krok 3: přidáme vousy a samostatné body za nimi"
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank()
  )
```

::: {.box-data collapse="true" title="Doplňující: jak určíme bod za vousy?"}
Nejdříve pravidlo zapíšeme slovy:

$$
\begin{align}
\text{dolní hranice}
&=
\text{dolní kvartil}
-
1{,}5
\times
\text{IQR}
\\
\text{horní hranice}
&=
\text{horní kvartil}
+
1{,}5
\times
\text{IQR}
\end{align}
$$

Pro tělesnou hmotnost dosadíme hodnoty z našeho souboru:

$$
\begin{align}
\text{dolní hranice}
&=
`r math_q1_hmotnost`
-
1{,}5
\times
`r math_iqr_hmotnost`
\\
&=
`r math_hranice_dolni_hmotnost`\ \text{kg}
\\
\text{horní hranice}
&=
`r math_q3_hmotnost`
+
1{,}5
\times
`r math_iqr_hmotnost`
\\
&=
`r math_hranice_horni_hmotnost`\ \text{kg}
\end{align}
$$

Obecně:

$$
\begin{align}
L &= Q_1 - 1{,}5 \times \text{IQR}
\\
U &= Q_3 + 1{,}5 \times \text{IQR}
\end{align}
$$

Zde $L$ označuje dolní hranici, $U$ horní hranici, $Q_1$ dolní kvartil a $Q_3$
horní kvartil. Bod menší než $L$ nebo větší než $U$ se vykreslí samostatně.
Vous nekončí přímo na vypočtené hranici, ale na nejkrajnější **skutečně
pozorované hodnotě**, která ještě leží uvnitř hranice.
:::

::: {.box-warning title="Bod za vousy není automaticky chyba"}

Pravidlo 1,5 × `r render_glossary_term("iqr", display = "IQR")` označuje hodnotu
k bližšímu prozkoumání. Bod může být
překlep, zvláštní měření nebo zcela reálný biologický druh. O jeho významu
rozhodujeme podle zdroje dat a biologického kontextu, ne podle grafu samotného.
:::

Ve všech následujících krabicových grafech označujeme jako možné odlehlé hodnoty
**stejné druhy podle hranic vypočtených v původních kilogramech**. Logaritmická
osa mění pouze rozestupy mezi body, nikoli pravidlo pro jejich označení.

### Výsledný krabicový graf

R sestaví stejné prvky jedním příkazem.

::: {.panel-tabset}
#### Graf

```{r}
#| label: boxplot-finalni-hmotnosti
#| echo: false
#| message: false
#| warning: false
#| fig-height: 2.6
ggplot2::ggplot(
  data = data_boxplot_hmotnost
) +
  ggplot2::geom_boxplot(
    mapping = ggplot2::aes(
      y = skupina,
      xmin = vous_dolni,
      xlower = q1,
      xmiddle = median,
      xupper = q3,
      xmax = vous_horni
    ),
    stat = "identity",
    orientation = "y",
    fill = col_fill,
    color = col_data,
    width = 0.42
  ) +
  ggplot2::geom_point(
    data = tibble::tibble(
      hmotnost_kg = vec_odlehle_hmotnost
    ),
    mapping = ggplot2::aes(
      x = hmotnost_kg,
      y = ""
    ),
    inherit.aes = FALSE,
    shape = 21,
    color = col_data,
    fill = col_data,
    size = 2.4
  ) +
  ggplot2::scale_x_log10(
    breaks = c(0.01, 0.1, 1, 10, 100, 1000),
    labels = c("0,01", "0,1", "1", "10", "100", "1000")
  ) +
  ggplot2::labs(
    x = "Tělesná hmotnost (kg; logaritmická osa)",
    y = NULL,
    title = "Krabicový graf tělesné hmotnosti"
  ) +
  ggplot2::theme(
    axis.text.y = ggplot2::element_blank(),
    axis.ticks.y = ggplot2::element_blank(),
    panel.grid.major.y = ggplot2::element_blank()
  )
```

#### Kód v R

```{r}
#| label: boxplot-finalni-hmotnosti-kod
#| echo: true
#| eval: true
#| fig-height: 2.6
# Vytvoříme vodorovný krabicový graf.
boxplot(
  x = vec_hmotnost_kg,
  horizontal = TRUE,
  log = "x",
  col = "#D8C9E8",
  outpch = 21,
  outcol = "#6B7280",
  outbg = "#6B7280",
  xlab = "Tělesná hmotnost (kg; logaritmická osa)",
  main = "Krabicový graf tělesné hmotnosti"
)
```
:::

| Prvek | Co znamená |
|---|---|
| čára uvnitř krabice | medián, tedy 50. percentil |
| levý a pravý okraj krabice | Q1 a Q3 |
| šířka krabice | IQR, tedy prostřední polovina hodnot |
| vousy | nejkrajnější hodnoty uvnitř hranice 1,5 × IQR |
| samostatné body | možné odlehlé hodnoty za vousy |

### Když chceme vidět tvar: houslový graf

**Houslový graf** (anglicky *violin plot*) zachovává hladký obrys `r render_glossary_term("rozdeleni", display = "rozdělení")`: čím je „housle“ v určité části širší, tím více hodnot se v této oblasti soustředí.
<!-- TODO: add slug houslovy-graf to pojmy.yaml -->

Krabicový graf rychle ukáže medián, kvartily a možné odlehlé hodnoty, ale neukáže, zda se hodnoty hromadí v jednom nebo několika shlucích. V takové situaci může být houslový graf informativnější. Úzký boxplot uvnitř ponechává známé souhrny a obrys kolem něj doplňuje tvar dat.

Obecný základní zápis může vypadat takto:

```{r}
#| label: houslovy-graf-zakladni-kod
#| echo: true
#| eval: false
# Jedna housle zobrazí rozdělení hodnot v každé skupině.
ggplot2::ggplot(
  data = data_mereni,
  mapping = ggplot2::aes(
    x = skupina,
    y = hodnota
  )
) +
  ggplot2::geom_violin()
```

Názvy `data_mereni`, `skupina` a `hodnota` nahradíme názvy z vlastních dat.

```{r}
#| label: pripravit-pokrocily-houslovy-graf
#| echo: false
#| message: false
#| warning: false
data_odlehle_hmotnost <-
  tibble::tibble(
    hmotnost_kg = vec_odlehle_hmotnost
  )

plot_housle_hmotnost <-
  ggplot2::ggplot(
    data = data_hmotnost,
    mapping = ggplot2::aes(
      x = hmotnost_kg,
      y = ""
    )
  ) +
  ggplot2::geom_violin(
    orientation = "y",
    trim = FALSE,
    fill = col_fill,
    color = col_data
  ) +
  ggplot2::geom_boxplot(
    data = data_boxplot_hmotnost,
    mapping = ggplot2::aes(
      y = skupina,
      xmin = vous_dolni,
      xlower = q1,
      xmiddle = median,
      xupper = q3,
      xmax = vous_horni
    ),
    stat = "identity",
    orientation = "y",
    width = 0.14,
    fill = "white",
    inherit.aes = FALSE
  ) +
  ggplot2::geom_point(
    data = data_odlehle_hmotnost,
    mapping = ggplot2::aes(
      x = hmotnost_kg,
      y = ""
    ),
    inherit.aes = FALSE,
    shape = 21,
    color = col_data,
    fill = col_data,
    size = 2.4
  ) +
  ggplot2::geom_vline(
    xintercept = prumer_hmotnost,
    color = col_mean,
    linewidth = 1.3
  ) +
  ggplot2::scale_x_log10(
    breaks = c(0.01, 0.1, 1, 10, 100, 1000),
    labels = c("0,01", "0,1", "1", "10", "100", "1000")
  ) +
  ggplot2::labs(
    x = "Tělesná hmotnost (kg; logaritmická osa)",
    y = NULL
  )
```

*Kde je housle nejširší? Dokázali byste tuto informaci vyčíst ze samotného
krabicového grafu? Jak daleko od sebe leží
`r render_glossary_term("prumer", display = "průměr")` a medián?*

```{r}
#| label: houslovy-graf-hmotnosti
#| echo: false
#| fig-height: 2.5
#| fig-cap: "Oranžová svislá čára označuje aritmetický průměr, čára uvnitř krabice medián a šedé body možné odlehlé hodnoty."
plot_housle_hmotnost
```

```{=typst}
#pagebreak()
```

::: {.box-data collapse="true" title="Doplňující: úplný kód kombinovaného grafu"}
Tento kód navazuje na výpočet kvartilů, vousů, možných odlehlých hodnot a
průměru v předchozí části.

```{r}
#| label: houslovy-graf-pokrocily-kod
#| echo: true
#| eval: false
# Přidáme ke tvaru rozdělení krabici, body za vousy a průměr.
ggplot2::ggplot(
  data = data_hmotnost,
  mapping = ggplot2::aes(x = hmotnost_kg, y = "")
) +
  ggplot2::geom_violin(
    orientation = "y", trim = FALSE,
    fill = "#D8C9E8", color = "#6B7280"
  ) +
  ggplot2::geom_boxplot(
    data = data_boxplot_hmotnost,
    mapping = ggplot2::aes(
      y = skupina,
      xmin = vous_dolni, xlower = q1, xmiddle = median,
      xupper = q3, xmax = vous_horni
    ),
    stat = "identity", orientation = "y", width = 0.14,
    fill = "white", inherit.aes = FALSE
  ) +
  ggplot2::geom_point(
    data = data_odlehle_hmotnost,
    mapping = ggplot2::aes(x = hmotnost_kg, y = ""),
    inherit.aes = FALSE, shape = 21,
    color = "#6B7280", fill = "#6B7280", size = 2.4
  ) +
  ggplot2::geom_vline(
    xintercept = prumer_hmotnost,
    color = "#F3A712", linewidth = 1.3
  ) +
  ggplot2::scale_x_log10() +
  ggplot2::labs(
    x = "Tělesná hmotnost (kg; logaritmická osa)",
    y = NULL
  )
```
:::

Průměr přidáváme pouze do kombinovaného grafu, abychom vedle tvaru rozdělení
viděli oba způsoby popisu středu. Houslový graf ale také vyhlazuje data. U
malého souboru proto mohou být poctivější jednotlivé body; žádný typ grafu není
nejlepší ve všech situacích.

::: {.box-data collapse="true" title="Doplňující: co tento souhrnný graf skrývá?"}

Krabicový graf je kompaktní a dobře se skládá vedle dalších skupin, ale skrývá
jednotlivé hodnoty i podrobný tvar rozdělení. Dva různé soubory mohou mít stejný
boxplot. Když je to možné, doplňte jej body, houslovým grafem nebo se vraťte k
`r render_glossary_term("histogram", display = "histogramu")`.
:::

## Typy proměnných: zobecnění na konci

Doteď jsme sledovali hlavně jednu
`r render_glossary_term("promenna", display = "proměnnou")`: dobu spánku savce
za den. Teprve
teď máme dost zkušeností, abychom si položili obecnější otázku:
**jaký druh informace proměnná nese?**

U jednoho savce bychom mohli zaznamenat například:

- dobu spánku v hodinách;
- hmotnost v kilogramech;
- počet pozorovaných jedinců;
- typ potravy;
- velikostní kategorii.

Tyto údaje nelze popisovat ani zobrazovat všechny stejným způsobem.
Stejné zapsané číslo totiž může znamenat něco úplně jiného:

Nejprve proto určujeme
`r render_glossary_term("jednotka-pozorovani", display = "pozorovací jednotku")`:
koho nebo co jeden řádek reprezentuje.

| Zápis | Co znamená | Typ proměnné |
|---:|---|---|
| 37,0 | tělesná teplota 37,0 °C | `r render_glossary_term("spojita-promenna", display = "numerická spojitá")` |
| 37 | počet rostlin na ploše | `r render_glossary_term("diskretni-promenna", display = "numerická diskrétní")` |
| 37 | číselný kód lokality | `r render_glossary_term("nominalni-promenna", display = "kategoriální nominální")` |
| 3 | hodnocení na škále 1–5 | `r render_glossary_term("ordinalni-promenna", display = "kategoriální ordinální")` |

::: {.box-rule title="Typ proměnné neurčuje vzhled hodnoty"}
O typu proměnné rozhoduje **význam hodnot a způsob jejich vzniku**, ne to, zda
jsou v tabulce zapsány číslem nebo slovem.
:::

::: {.box-rule title="Statistický typ není totéž co třída objektu v R"}
R popisuje technickou podobu objektu pomocí `class()` a `typeof()`. Funkce `str()` ukáže jeho stručnou strukturu a několik hodnot. Tyto kontroly jsou velmi užitečné, ale samy nerozhodnou, zda je proměnná spojitá, diskrétní, nominální nebo ordinální. K tomu stále potřebujeme vědět, co hodnoty znamenají a jak vznikly.
:::

Při určování typu si zkuste doplnit větu:

> Jeden řádek představuje ___ a tato proměnná říká ___.

Tím se zároveň vracíte k pozorovací jednotce. Počet druhů v jednom řádu může být
například vlastností lokality, zatímco řád savce je vlastností druhu.

### Numerická spojitá proměnná

**Numerická spojitá proměnná** (*continuous numerical variable*; vyhledávací
termín *continuous data*) vzniká měřením. Mezi dvěma hodnotami si obvykle umíme
představit další možné hodnoty, i když je přístroj zaokrouhlí.

Příklady z reálného světa:

- délka těla nebo listu,
- tělesná hmotnost,
- teplota,
- koncentrace látky,
- doba spánku.

**Jak ji uvidíme v R?**

```{r}
#| label: spojita-priklad-kod
#| eval: true

# Vybereme sloupec s naměřenou dobou spánku.
vec_spanek_h <- ggplot2::msleep[["sleep_total"]]

# Zobrazíme prvních šest hodnot.
head(vec_spanek_h)

# Zjistíme třídu objektu, jak ji popisuje R.
class(vec_spanek_h)

# Zjistíme, jak jsou hodnoty technicky uložené.
typeof(vec_spanek_h)

# Získáme stručný přehled o struktuře objektu.
str(vec_spanek_h)
```

R tento vektor zobrazí jako `numeric` a technicky jej uloží jako `double`. Z toho ještě nepozná, že jde o spojitou proměnnou. To usuzujeme z významu: doba spánku vznikla měřením a mezi dvěma hodnotami si umíme představit další.

Pro spojitou proměnnou jsme už použili čtyři vhodné grafy: bodový graf,
`r render_glossary_term("histogram", display = "histogram")`, graf hustoty a
`r render_glossary_term("boxplot", display = "krabicový graf")`.

::: {.panel-tabset}

#### Bodový graf

Ukazuje každé pozorování. Je výborný pro malý až střední soubor.

```{r}
#| label: spojita-galerie-body
#| echo: false
#| fig-cap: "Každá tečka představuje jeden druh savce."
#| fig-height: 2.1

ggplot2::ggplot(data_spanek, ggplot2::aes(x = spanek_h, y = 0)) +
  ggbeeswarm::geom_quasirandom(
    width = 0.38,
    orientation = "y",
    size = 2.2,
    alpha = 0.70,
    color = col_data
  ) +
  ggplot2::scale_y_continuous(NULL, breaks = NULL) +
  ggplot2::coord_cartesian(ylim = c(-0.42, 0.42)) +
  ggplot2::labs(x = "Celková doba spánku [h/den]")
```

#### Histogram

Sdružuje hodnoty do intervalů. Hodí se, když chceme vidět tvar
`r render_glossary_term("rozdeleni", display = "rozdělení")`.

```{r}
#| label: spojita-galerie-histogram
#| echo: false
#| fig-cap: "Histogram spojité proměnné; vzhled závisí na šířce košů."
#| fig-height: 3.4

ggplot2::ggplot(data_spanek, ggplot2::aes(x = spanek_h)) +
  ggplot2::geom_histogram(
    binwidth = 2,
    boundary = 0,
    fill = col_fill,
    color = "white"
  ) +
  ggplot2::labs(
    x = "Celková doba spánku [h/den]",
    y = "Počet druhů"
  )
```

#### Graf hustoty

Nabízí vyhlazený pohled na tvar rozdělení. Vyhlazení je analytické rozhodnutí,
nikoli další měření.

```{r}
#| label: spojita-galerie-hustota
#| echo: false
#| fig-cap: "Vyhlazený odhad hustoty spojité proměnné."
#| fig-height: 3.4

ggplot2::ggplot(data_spanek, ggplot2::aes(x = spanek_h)) +
  ggplot2::geom_density(
    fill = col_fill,
    color = col_data,
    linewidth = 1,
    alpha = 0.65
  ) +
  ggplot2::labs(
    x = "Celková doba spánku [h/den]",
    y = "Hustota"
  )
```

#### Krabicový graf

Zhušťuje data do
`r render_glossary_term("median", display = "mediánu")`,
`r render_glossary_term("kvantil", display = "kvartilů")`, vousů a
případných
`r render_glossary_term("odlehla-pozorovani", display = "odlehlých pozorování")`.

```{r}
#| label: spojita-galerie-boxplot
#| echo: false
#| fig-cap: "Krabicový graf stejné spojité proměnné."
#| fig-height: 2.6

ggplot2::ggplot(data_spanek, ggplot2::aes(x = spanek_h, y = "")) +
  ggplot2::geom_boxplot(
    fill = col_fill,
    color = col_data,
    width = 0.45,
    outlier.shape = 21,
    outlier.color = col_data,
    outlier.fill = col_data,
    outlier.size = 2.4
  ) +
  ggplot2::labs(
    x = "Celková doba spánku [h/den]",
    y = NULL
  )
```

:::

### Numerická diskrétní proměnná

**Numerická diskrétní proměnná** (*discrete numerical variable*, také *count
data*) vzniká nejčastěji počítáním. Možné hodnoty jsou oddělené: mezi 4 a 5
mláďaty není 4,6 mláděte.

Příklady:

- počet mláďat,
- počet druhů na lokalitě,
- počet semen,
- počet návštěv květu,
- počet přečtených sekvencí.

Oba počty jsou diskrétní, ale při volbě grafu a souhrnu záleží také na rozsahu možných hodnot a biologické otázce: počet mláďat mívá jen několik hodnot, zatímco počet listů na stromě může být velmi vysoký. Samotný štítek „diskrétní“ nám proto neurčí jeden univerzální graf.

V našem datasetu můžeme změnit pozorovací jednotku a spočítat, kolik druhů
zastupuje každý taxonomický řád:

**Jak ji uvidíme v R?**

```{r}
#| label: diskretni-priklad-kod
#| eval: true

# Spočítáme druhy v každém taxonomickém řádu.
cetnosti_radu <- table(ggplot2::msleep[["order"]])

# Ponecháme jen vypočtené počty bez názvů řádů.
vec_pocet_druhu <- as.integer(cetnosti_radu)

# Zobrazíme prvních šest počtů.
head(vec_pocet_druhu)

# Zjistíme třídu objektu, jak ji popisuje R.
class(vec_pocet_druhu)

# Zjistíme, jak jsou hodnoty technicky uložené.
typeof(vec_pocet_druhu)

# Získáme stručný přehled o struktuře objektu.
str(vec_pocet_druhu)
```

R vrátí třídu i způsob uložení `integer`, protože jsme vytvořili vektor celých počtů. Ani `integer` ale automaticky neznamená diskrétní proměnnou: například zaokrouhlená teplota může být také zapsána celým číslem. Rozhodující je, že zde druhy skutečně počítáme.

```{r}
#| label: diskretni-priprava
#| echo: false

data_rady <- data_savci |>
  dplyr::count(rad, name = "pocet_druhu") |>
  dplyr::arrange(dplyr::desc(pocet_druhu))
```

Takovou `r render_glossary_term("cetnost", display = "četnost")` můžeme
zobrazit jako body nebo
`r render_glossary_term("sloupcovy-graf", display = "sloupcový graf")`.

::: {.panel-tabset}

#### Bodový graf četností

```{r}
#| label: diskretni-graf-body
#| echo: false
#| fig-cap: "Počet druhů savců zastoupených v jednotlivých taxonomických řádech."

ggplot2::ggplot(
  data_rady,
  ggplot2::aes(x = reorder(rad, pocet_druhu), y = pocet_druhu)
) +
  ggplot2::geom_segment(
    ggplot2::aes(xend = rad, y = 0, yend = pocet_druhu),
    color = col_fill,
    linewidth = 1.2
  ) +
  ggplot2::geom_point(size = 3, color = col_data) +
  ggplot2::coord_flip() +
  ggplot2::labs(
    x = "Taxonomický řád",
    y = "Počet druhů"
  )
```

#### Sloupcový graf

```{r}
#| label: diskretni-graf-sloupce
#| echo: false
#| fig-cap: "Sloupcový graf týchž počtů."

ggplot2::ggplot(
  data_rady,
  ggplot2::aes(x = reorder(rad, pocet_druhu), y = pocet_druhu)
) +
  ggplot2::geom_col(fill = col_fill, color = col_data) +
  ggplot2::coord_flip() +
  ggplot2::labs(
    x = "Taxonomický řád",
    y = "Počet druhů"
  )
```

:::

U diskrétních dat můžeme použít také histogram, ale jeho koše musí respektovat
jednotlivé možné hodnoty.
`r render_glossary_term("prumer", display = "Průměr")` může být smysluplný i
tehdy, když sám není
možným pozorováním: průměrný počet mláďat může být 2,4, přestože žádné zvíře
nemělo „0,4 mláděte“.

### Kategoriální nominální proměnná

**Kategoriální nominální proměnná** (*nominal categorical variable*; *nominal
data*) rozděluje pozorování do kategorií, které nemají přirozené pořadí.

Příklady:

- druh nebo taxonomický řád,
- typ potravy,
- barva květu,
- krevní skupina,
- studijní skupina.

Pro nominální proměnnou obvykle zjišťujeme
**`r render_glossary_term("cetnost", display = "četnosti")`**
(*counts/frequencies*)
nebo podíly kategorií. Průměr kódů kategorií nedává biologický smysl.

**Jak ji uvidíme v R?**

```{r}
#| label: nominalni-priklad-kod
#| eval: true

# Vybereme sloupec s typem potravy.
vec_typ_potravy <- ggplot2::msleep[["vore"]]

# Chybějící údaje označíme viditelnou kategorií.
vec_typ_potravy[is.na(vec_typ_potravy)] <- "neuvedeno"

# Řekneme R, že hodnoty představují kategorie.
vec_typ_potravy <- factor(vec_typ_potravy)

# Zjistíme třídu objektu, jak ji popisuje R.
class(vec_typ_potravy)

# Zjistíme, jak jsou kategorie technicky uložené.
typeof(vec_typ_potravy)

# Zobrazíme strukturu včetně názvů kategorií.
str(vec_typ_potravy)

# Spočítáme zastoupení jednotlivých kategorií.
table(vec_typ_potravy)
```

R zobrazuje nominální kategorie jako `factor` s několika úrovněmi (*levels*). `typeof()` přesto vrátí `integer`, protože faktor používá celá čísla jen jako vnitřní kódy pro textové štítky. Tyto kódy nejsou měření a nemá smysl je průměrovat.

```{r}
#| label: nominalni-priprava
#| echo: false

data_potrava <- data_savci |>
  dplyr::transmute(typ_potravy = potrava) |>
  dplyr::count(typ_potravy, name = "pocet_druhu") |>
  dplyr::mutate(
    podil = pocet_druhu / sum(pocet_druhu),
    typ_potravy = reorder(typ_potravy, pocet_druhu)
  )
```

::: {.panel-tabset}

#### Četnosti

```{r}
#| label: nominalni-graf-cetnosti
#| echo: false
#| fig-cap: "Počet druhů v jednotlivých kategoriích potravy."

ggplot2::ggplot(
  data_potrava,
  ggplot2::aes(x = typ_potravy, y = pocet_druhu)
) +
  ggplot2::geom_col(fill = col_fill, color = col_data) +
  ggplot2::coord_flip() +
  ggplot2::labs(
    x = "Typ potravy",
    y = "Počet druhů"
  )
```

#### Podíly

```{r}
#| label: nominalni-graf-podily
#| echo: false
#| fig-cap: "Podíl druhů v jednotlivých kategoriích potravy."

ggplot2::ggplot(
  data_potrava,
  ggplot2::aes(x = typ_potravy, y = podil)
) +
  ggplot2::geom_col(fill = col_fill, color = col_data) +
  ggplot2::coord_flip() +
  ggplot2::scale_y_continuous(
    labels = scales::label_percent(decimal.mark = ",")
  ) +
  ggplot2::labs(
    x = "Typ potravy",
    y = "Podíl druhů"
  )
```

:::

::: {.box-warning title="Číselný kód není měření"}
Když lokalitám přidělíme kódy 1, 2 a 3, nevznikne tím numerická proměnná.
Výpočet průměru těchto kódů by závisel jen na našem libovolném číslování.
:::

### Kategoriální ordinální proměnná

**Kategoriální ordinální proměnná** (*ordinal categorical variable*; *ordinal
data*) má kategorie s přirozeným pořadím, ale vzdálenosti mezi nimi nemusí být
stejné.

Příklady:

- malý – střední – velký,
- mírný – střední – silný symptom,
- vývojové stadium,
- odpověď na škále „nesouhlasím“ až „souhlasím“,
- stupeň poškození listu.

V datasetu rozlišujeme tři seřazené velikostní kategorie:
**lehký – střední – těžký**.

**Jak ji uvidíme v R?**

```{=typst}
#pagebreak()
```

```{r}
#| label: ordinalni-priklad-kod
#| eval: true

# Vybereme sloupec s uspořádanou velikostní kategorií.
vec_velikost <- data_savci[["velikost"]]

# Pro tuto ukázku vynecháme řádky bez uvedené kategorie.
vec_velikost <- vec_velikost[!is.na(vec_velikost)]

# Zjistíme třídu objektu, jak ji popisuje R.
class(vec_velikost)

# Zjistíme, jak jsou kategorie technicky uložené.
typeof(vec_velikost)

# Zobrazíme strukturu včetně pořadí kategorií.
str(vec_velikost)

# Spočítáme zastoupení jednotlivých kategorií.
table(vec_velikost)
```

R tento objekt označí třídami `ordered` a `factor`. Vnitřní uložení je opět `integer`, ale pořadí úrovní „lehký“ < „střední“ < „těžký“ je součástí objektu. Právě tím se ordinální faktor liší od nominálního faktoru.

```{r}
#| label: ordinalni-priprava
#| echo: false

data_velikost <- data_savci |>
  dplyr::filter(!is.na(velikost)) |>
  dplyr::count(velikost, name = "pocet_druhu")
```

```{r}
#| label: ordinalni-graf
#| echo: false
#| fig-cap: "U ordinální proměnné zachováváme přirozené pořadí kategorií."

ggplot2::ggplot(
  data_velikost,
  ggplot2::aes(x = velikost, y = pocet_druhu)
) +
  ggplot2::geom_col(fill = col_fill, color = col_data) +
  ggplot2::labs(
    x = "Velikostní kategorie",
    y = "Počet druhů"
  )
```

::: {.box-rule title="U ordinální proměnné zachováváme pořadí"}
Kategorie nejsou zaměnitelné: **lehký < střední < těžký**. Toto pořadí musí
zůstat zachované v objektu v R, v tabulce i v grafu.
:::

### Procvičení: určete typ proměnné

Možnosti jsou:

- numerická spojitá;
- numerická diskrétní;
- kategoriální nominální;
- kategoriální ordinální.

Určete typ každé proměnné. Zatím nemusíte vybírat graf:

1. pH vody v rybníce,
2. počet žab odchycených za noc,
3. druh stanoviště,
4. stupeň napadení rostliny: žádný – mírný – silný,
5. identifikační číslo jedince.

::: {.box-result collapse="true" title="Řešení: určete typ proměnné"}
1. pH: numerická spojitá.
2. Počet žab: numerická diskrétní.
3. Druh stanoviště: kategoriální nominální.
4. Stupeň napadení: kategoriální ordinální.
5. Identifikační číslo: identifikátor, nikoli měřená numerická proměnná.
:::

### Přehled: od typu proměnné k vhodnému popisu

| Typ proměnné | Příklad | Vhodný číselný popis | Vhodné grafy | Anglický termín |
|---|---|---|---|---|
| numerická spojitá | doba spánku | medián + `r render_glossary_term("iqr", display = "IQR")` nebo průměr + `r render_glossary_term("smerodatna-odchylka", display = "SD")` | bodový graf, histogram, hustota, boxplot | *continuous numerical* |
| numerická diskrétní | počet mláďat | četnosti; někdy medián/průměr | bodový, sloupcový nebo vhodně nastavený histogram | *discrete numerical, count data* |
| kategoriální nominální | typ potravy | četnosti a podíly | sloupcový graf | *nominal categorical* |
| kategoriální ordinální | stupeň poškození | četnosti; medián pořadí jen opatrně | uspořádaný sloupcový graf | *ordinal categorical* |

::: {.box-rule title="Pořadí rozhodování"}
1. Co představuje jeden řádek?
2. Co proměnná znamená a jak vznikla?
3. Jakého je typu?
4. Který graf ukáže jednotlivé hodnoty nebo rozdělení?
5. Který číselný souhrn odpovídá tvaru dat a biologické otázce?
:::

```{=typst}
#pagebreak()
```

## Shrnutí

V této lekci jsme prošli celou cestu od měření k popisu dat:

1. jedno `r render_glossary_term("pozorovani", display = "pozorování")` jsme
   zapsali do řádku tabulky;
2. jednu `r render_glossary_term("promenna", display = "proměnnou")` jsme
   vybrali jako vektor v R a zkontrolovali pomocí
   `length()` a `head()`;
3. před výpočtem statistik jsme se podívali na jednotlivé hodnoty a
   `r render_glossary_term("rozdeleni", display = "rozdělení")`;
4. `r render_glossary_term("prumer", display = "průměr")`,
   `r render_glossary_term("median", display = "medián")`,
   `r render_glossary_term("kvantil", display = "kvartily")`,
   `r render_glossary_term("iqr", display = "IQR")`, minimum, maximum a
   `r render_glossary_term("smerodatna-odchylka", display = "SD")` jsme
   propojili s grafem;
5. krok za krokem jsme z těchto myšlenek postavili
   `r render_glossary_term("boxplot", display = "krabicový graf")`;
6. nakonec jsme rozlišili
   `r render_glossary_term("spojita-promenna", display = "spojité")`,
   `r render_glossary_term("diskretni-promenna", display = "diskrétní")`,
   `r render_glossary_term("nominalni-promenna", display = "nominální")` a
   `r render_glossary_term("ordinalni-promenna", display = "ordinální")`
   proměnné.

Neexistuje jedno „nejlepší“ číslo ani jeden „nejlepší“ graf pro všechna data.
Pro číselná data často používáme dvě užitečné dvojice:
**průměr + SD** nebo **medián + IQR**. Volba závisí na typu proměnné, tvaru dat,
`r render_glossary_term("jednotka-pozorovani", display = "pozorovací jednotce")`
a otázce, kterou chceme zodpovědět.

**Význam proměnné určuje její statistický typ.** Teprve podle něj vybíráme
smysluplný graf a číselný souhrn. A stejně jako u titulku o „běžném“ savci platí:
správný výpočet ještě nestačí — musíme vidět data a vědět, co představuje jeden
řádek.

### Závěrečná otázka

Představte si nový dataset o rostlinách. Každý řádek je jedna rostlina a sloupce
obsahují druh, výšku, počet květů a stupeň poškození listů.

> Kterou proměnnou byste prozkoumali jako první, jakým grafem a jakou dvojicí
> statistik? Dokážete svou volbu zdůvodnit?

## Most k další lekci

Zatím jsme zkoumali vždy jednu
`r render_glossary_term("promenna", display = "proměnnou")`. V další lekci se
zaměříme na otázku,
jak data získat, načíst a uspořádat tak, aby byla připravena pro podobné grafy a
výpočty. Později začneme porovnávat skupiny a hledat vztahy mezi proměnnými.

## Slovníček

```{r}
#| label: glossary-table
#| echo: false
#| results: asis
if (knitr::is_html_output()) {
  cat(
    "<p>V HTML verzi se definice pojmů zobrazují také po najetí kurzorem ",
    "na podtržený pojem.</p>",
    sep = ""
  )
  glossary::glossary_table()
} else {
  cat(
    "Interaktivní definice pojmů jsou dostupné v HTML verzi materiálů a ",
    "v online slovníčku: ",
    "https://cuni-natur-biostatistics.github.io/slovnik/.\n",
    sep = ""
  )
}
```
