
Jak se píše dobrý skript
Co je to vlastně dobrý skript? Dobrý skript je soubor příkazů a funkcí používaných k analýze dat, který splňuje následující předpoklady:
1. Dobře čitelný, srozumitelný nejen pro autora, ale i pro další uživatele - je jednoznačné k čemu slouží každý z příkazů, je zřejmé, jakým způsobem byly načteny data a odkud, není problém analýzu zopakovat krok po kroku i pro nezasvěcenou osobu.
2. Není zbytečně dlouhý a je optimalizován z výpočetního hlediska - čím kratší kód, tím lépe, ale ne na úkor srozumitelnosti, algoritmy by měli být optimalizovány co se časové náročnosti týče.
3. Obsahuje kontrolní body - ověření předpokladů a výstupů z funkcí s chybovou hláškou v případě jejich nesplnění upozorní na špatný výpočet dopředu.
My si zde vyjmenujeme podrobněji pět základních zásad, které byste měli dodržovat, aby byl Váš kód opravdu dobrý a Vaše práce příjemnější a rychlejší.
Zásada č.1 - Pracujte vždy se zdrojovým kódem, pokud možno v chytrém editoru!
Pracujte se skripty a funkcemi - vše si dobře zapisujte a ukládejte; v případě problémů změňte kód, který problém produkuje, neměňte výstup!)
Používejte chytrý editor, který dokáže:
- Kontrolovat syntax: závorky „(...))“, zvýraznění kódu (odlišné fonty a barvy)
- Umí vyhodnotit R kód: v řádku, regionu, ve funkci i v celém souboru
- Dokáže doplňovat automaticky názvy R objektů nebo cest k souborům (obvykle s pomocí klávesy TAB)
Nejlepším editorem je R-studio, které zároveň umožňuje spouštění příkazů a zobrazuje výsledky, nápovědu i historii příkazů.
Další dobré editory jsou Emacs + ESS ('Enacs Speaks Statistics'), WinEdt + R-WinEdt.
Zásada č.2 - Pište srozumitelně a přehledně
Váš kód musí být srozumitelný nejen pro Vás v dané chvíli, ale i pro jiné. I když teď máte pocit, že si všechno pamatujete, garantujeme Vám, že za měsíc, dva, nebo půl roku se v skriptu už nebudete orientovat. O to víc to platí pro jiné, kteří mohou analýzu převzít po Vás.
Proto se tedy snažte aby byl Váš kód byl co nejvíce samovysvětlující, tedy:
- Názvy parametrů a proměnných by měly odrážet účel i konvenci, např. X,Y pro matici; x,y pro vektor; a,b pro konstanty
- Názvy funkcí by měly jasně identifikovat co funkce dělá - tvořte proto funkce názvem odmocnina, součet a ne funkce1, funkce2
- Nepoužívejte symboly/názvy, které jsou už „zadané“ (c je funkce concatenate, q je skratka funkce quit()...)
Pro přehlednost:
- Používejte odsazení řádků, například kód pro for cyklus by měl vypadat takhle:
for (i in 1:10)
{
a <- a+1
}
... a ne takhle:
for (i in 1:10)
{
a <- a+1
}
U kratšího for cyklu zvažte kód na jeden řádek:
for (i in 1:10){a <- a+1}
- Používejte mezery, hlavně u přiřazení = , <- :
a <- 2 místo a<-a+1
- Dlouhé příkazy pište do více řádků
- Používejte komentáře, nejlépe každých 10 řádků, vytvořte si systém, například:
' # # # ' - pro hlavní komentáře umístěné před kódem
' # #' - pro normální komentáře v kódu
' #' - pro komentáře na konci příkazu
### Popisná statistika ###
## Graf závislosti počtu lymfocytů v krvi na věku u mužů a žen
for (i in pohlavi)
{
plot(x[grp==i],y[grp==i])
} # end for i
POZOR, vyhněte se zbytečným komentářům, pokud je kód samovysvětlující. Příklad zbytečného komentáře:
## je-li i menší než 2, výpočet se ukončí
if (i<2) break()
-
Pokud je to možné, používejte if else pouze v zjednodušené formě:
X[i,j] <- if (podmínka) a else b
místo
if(podmínka) X[i,j] <- a
else X[i,j] <- b - Používejte <- pro přiřazení a = v argumentech funkce, symbol <- je v některých programech oddělený barevně a také je vizuálně přijatelnější než =:
a <- 2*b místo a=2*b
sum(a, b, na.rm = TRUE)
Zásada č. 3 - Nekopírujte části kódu
Pokud nějakou část kódu opakujete často, nekopírujte jej ze skriptu do skriptu, ale vytvořte z daného kódu funkci. Tím kód zpřehledníte, minimalizujete chyby a jednoduše aplikujete případné změny úplně všude pouhým odvoláním se na funkci.
Zásada č. 4: Organizujte správně svoje funkce
Název funkce by měl odrážet to, co funkce dělá.
- Ve funkci se nikdy neodkazujte na globální proměnné definované mimo funkci
b <- 2
soucet <- function(x)
{
res <- x + b
return(res)
}
V záhlaví funkce okomentujte co funkce dělá společně s jejími argumenty a jejich formátem:
# funkce součet() sečte vektor x a konstantu b
# x - numerický vektor
# b - konstanta (číslo)
soucet <- function(x, b)
{
res <- x + b
return(res)
}
Ukládejte vždy jednu funkci do .R souboru pod stejným názvem, který má funkce (např. funkce s názvem soucet uložená do souboru soucet.R). Budete-li funkci definovat pouze ve skriptu k analýze, nebudete ji moci najít a využít pro použití v další analýze.
Pokud máte více funkcí v jednom typu analýzy, zorganizujte je do R balíku a napište k němu vignette (návod na použití).
Zásada č. 5 - Optimalizujte algoritmus
Snažte se používat co nejoptimálnější a nejrychlejší verze funkcí, nové algoritmy sestavte tak, aby byly co nejméně časově a paměťově náročné. V R to platí obzvlášť, protože funguje systémem pass by value - tedy všechny objekty kopíruje.
- Pro náročnější funkce zvažte použití paralelizace a programování v C++, Python nebo Perl
- Pokud je to možné, vyhněte se vnořeným cyklům:
for (i in 1:10)
{
for (j in 1:10)
{
for (k in 1:10)
{
...
}
}
}
... a použijte místo nich vektorizované funkce (například funkce z rodiny apply). Spřehledníte tím kód a ve většině případů (ne vždy!) ho i zrychlíte:
- Inicializujte nové objekty v plné velikosti před for cyklem
- Více o optimalizaci for() cyklu jsme si již řekli v kapitole Cykly a podmínky
- Používejte funkci system.time() pro testování časové náročnosti funkce/kódu:
> system.time({j<-0; for(i in 1:10000000){j<-j+i}})
user system elapsed
0.000 0.000 3.075
Zásada 6: Testujte svůj kód
Používejte krátké příklady pro otestování svého kódu/funkcí, netestujte hned na velkých datech z analýzy! Riskovali byste tím, že si nevšimnete chyby.
Při odstraňování chyb postupujte systematicky:
1. Prečtěte si chybovou hlášku a identifikujte, v které časti kódu k ní dochází
2. Opravte chybu a testujte jen daný kousek kódu
3. Pamatujte, že v kódu může být více chyb a to i na tom samém řádku – vždy je potřebné kód vyzkoušet metodou zevnitř navenek – nejprve vyhodnotíte argumenty a jejich hodnoty, pokud jsou v pořádku, poté syntax a tak dále...