Jupyter notebook a programovací jazyk R

Otestování základní funkcionality kernelu jazyka R

In [1]:
print("Hello world!")
[1] "Hello world!"
In [2]:
"Hello world!"
'Hello world!'

Zobrazení nápovědy

In [36]:
help(sort)

Zobrazení příkladu použití

In [37]:
example(sort)
sort> require(stats)

sort> x <- swiss$Education[1:25]

sort> x; sort(x); sort(x, partial = c(10, 15))
 [1] 12  9  5  7 15  7  7  8  7 13  6 12  7 12  5  2  8 28 20  9 10  3 12  6  1
 [1]  1  2  3  5  5  6  6  7  7  7  7  7  8  8  9  9 10 12 12 12 12 13 15 20 28
 [1]  3  2  5  5  1  6  6  7  7  7  7  8  7  8  9  9 10 12 12 12 12 20 28 13 15

sort> ## illustrate 'stable' sorting (of ties):
sort> sort(c(10:3, 2:12), method = "shell", index.return = TRUE) # is stable
$x
 [1]  2  3  3  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11 12

$ix
 [1]  9  8 10  7 11  6 12  5 13  4 14  3 15  2 16  1 17 18 19


sort> ## $x : 2  3  3  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11 12
sort> ## $ix: 9  8 10  7 11  6 12  5 13  4 14  3 15  2 16  1 17 18 19
sort> sort(c(10:3, 2:12), method = "quick", index.return = TRUE) # is not
$x
 [1]  2  3  3  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11 12

$ix
 [1]  9  8 10 11  7  6 12  5 13  4 14  3 15  2 16 17  1 18 19


sort> ## $x : 2  3  3  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11 12
sort> ## $ix: 9 10  8  7 11  6 12  5 13  4 14  3 15 16  2 17  1 18 19
sort> 
sort> x <- c(1:3, 3:5, 10)

sort> is.unsorted(x)                  # FALSE: is sorted
[1] FALSE

sort> is.unsorted(x, strictly = TRUE) # TRUE : is not (and cannot be)
[1] TRUE

sort>                                 # sorted strictly
sort> ## Not run: 
sort> ##D ## Small speed comparison simulation:
sort> ##D N <- 2000
sort> ##D Sim <- 20
sort> ##D rep <- 1000 # << adjust to your CPU
sort> ##D c1 <- c2 <- numeric(Sim)
sort> ##D for(is in seq_len(Sim)){
sort> ##D   x <- rnorm(N)
sort> ##D   c1[is] <- system.time(for(i in 1:rep) sort(x, method = "shell"))[1]
sort> ##D   c2[is] <- system.time(for(i in 1:rep) sort(x, method = "quick"))[1]
sort> ##D   stopifnot(sort(x, method = "shell") == sort(x, method = "quick"))
sort> ##D }
sort> ##D rbind(ShellSort = c1, QuickSort = c2)
sort> ##D cat("Speedup factor of quick sort():\n")
sort> ##D summary({qq <- c1 / c2; qq[is.finite(qq)]})
sort> ##D 
sort> ##D ## A larger test
sort> ##D x <- rnorm(1e7)
sort> ##D system.time(x1 <- sort(x, method = "shell"))
sort> ##D system.time(x2 <- sort(x, method = "quick"))
sort> ##D system.time(x3 <- sort(x, method = "radix"))
sort> ##D stopifnot(identical(x1, x2))
sort> ##D stopifnot(identical(x1, x3))
sort> ## End(Not run)
sort> 
sort> 

Práce s vektory

Se základními konstruktory vektorů jsme se již v tomto seriálu seznámili, takže si nyní pouze připomeňme, že existuje hned několik způsobů konstrukce nového vektoru. V případě, že má vektor obsahovat jen jedinou hodnotu, je vytvoření takového vektoru jednoduché a přímočaré, protože vlastní zápis hodnoty (typicky čísla) již představuje skalární hodnotu, která se však chová jako vektor (má délku rovnou jedné, může se používat v operacích, kde se očekávají vektory atd.):

In [3]:
42
42

O tom, jakého typu je takový skalár nebo vektor, se můžeme přesvědčit zavoláním funkce class:

In [4]:
class(42)
'numeric'

Vektor s obecnými prvky se vytvoří konstruktorem nazvaným c, což je funkce, které se předají hodnoty jednotlivých prvků:

In [6]:
a <- c(1,2,3,4)
In [7]:
class(a)
'numeric'

Prvky samozřejmě nemusí být pouze celými čísly, ale například i hodnotami s plovoucí řádovou čárkou:

In [8]:
b <- c(1.2, 2.3, 3.4)
class(b)
'numeric'

Nakonec si vyzkoušíme vytvoření vektoru obsahujícího pravdivostní hodnoty TRUE a FALSE:

In [9]:
l <- c(TRUE, FALSE, TRUE)
class(l)
'logical'

Sekvence hodnot:

In [10]:
data <- 1:12
In [11]:
data
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12

Porovnání dvou vektorů (druhý vektor s jediným prvkem je rozšířen na velikost prvního vektoru):

In [12]:
data < 6
  1. TRUE
  2. TRUE
  3. TRUE
  4. TRUE
  5. TRUE
  6. FALSE
  7. FALSE
  8. FALSE
  9. FALSE
  10. FALSE
  11. FALSE
  12. FALSE

Matice

Pro vytvoření matice se používá konstruktor nazvaný matrix, kterému se předá vektor s daty (hodnotami prvků), počet řádků a počet sloupců (popř. obráceně):

In [7]:
m1 <- matrix(data, nrow=1, ncol=12)
In [8]:
m1
A matrix: 1 × 12 of type int
123456789101112
In [9]:
m2 <- matrix(data, nrow=3, ncol=4)
In [10]:
m2
A matrix: 3 × 4 of type int
14710
25811
36912
In [11]:
m3 <- matrix(data, nrow=4, ncol=3)
In [12]:
m3
A matrix: 4 × 3 of type int
15 9
2610
3711
4812

Zaplnění matice po řádcích nebo po sloupcích

V konstruktoru matrix je možné nepovinným parametrem (logickou hodnotou) byrow určit, zda bude matice zaplňována po řádcích nebo po sloupcích.

In [15]:
data <- 1:12
 
m1 <- matrix(data, nrow=1, ncol=12, byrow=TRUE)
m1
 
m2 <- matrix(data, nrow=2, ncol=6, byrow=TRUE)
m2
 
m3 <- matrix(data, nrow=3, ncol=4, byrow=TRUE)
m3
 
m4 <- matrix(data, nrow=4, ncol=3, byrow=TRUE)
m4
 
m5 <- matrix(data, nrow=6, ncol=2, byrow=TRUE)
m5
 
m6 <- matrix(data, nrow=12, ncol=1, byrow=TRUE)
m6
A matrix: 1 × 12 of type int
123456789101112
A matrix: 2 × 6 of type int
123 4 5 6
789101112
A matrix: 3 × 4 of type int
1 2 3 4
5 6 7 8
9101112
A matrix: 4 × 3 of type int
1 2 3
4 5 6
7 8 9
101112
A matrix: 6 × 2 of type int
1 2
3 4
5 6
7 8
910
1112
A matrix: 12 × 1 of type int
1
2
3
4
5
6
7
8
9
10
11
12

Pojmenování řádků a sloupců matice

Konstruktoru matrix postačuje předat v pojmenovaném parametru dimnames seznam vektorů, přičemž první vektor v seznamu obsahuje jména řádků a druhý vektor jména sloupců. Se seznamy jsme se sice prozatím nesetkali, ale ze zdrojového kódu dalšího demonstračního příkladu je patrné, že je jejich konstrukce pomocí list přímočará:

In [16]:
data <- 1:9
dimension.names <- list(
    c("x", "y", "z"),
    c("u", "v", "w"))
 
m33 <- matrix(data, nrow=3, ncol=3, dimnames=dimension.names)
m33
A matrix: 3 × 3 of type int
uvw
x147
y258
z369

Tisk tabulky s názvy měsíců

In [17]:
matrix(
  month.abb[c(12, 1:11)],
  nrow = 3,
  dimnames = list(
    c("start", "middle", "end"),
    c("Winter", "Spring", "Summer", "Fall")
  )
)
A matrix: 3 × 4 of type chr
WinterSpringSummerFall
startDecMarJunSep
middleJanAprJulOct
endFebMayAugNov

Maticový součin

In [19]:
data <- 1:25
 
m1 <- matrix(data, nrow=5, ncol=5)
m1
 
m2 <- diag(5)
m2
 
m1 %*% m2
 
m2[3,3] <- 10
m1 %*% m2
A matrix: 5 × 5 of type int
1 6111621
2 7121722
3 8131823
4 9141924
510152025
A matrix: 5 × 5 of type dbl
10000
01000
00100
00010
00001
A matrix: 5 × 5 of type dbl
1 6111621
2 7121722
3 8131823
4 9141924
510152025
A matrix: 5 × 5 of type dbl
1 61101621
2 71201722
3 81301823
4 91401924
5101502025

Výpočet inverzní matice

In [20]:
data <- c(2, 3, 2, 2)
 
m1 <- matrix(data, nrow=2, ncol=2)
m1
solve(m1)
 
m2 <- diag(5)
m2
solve(m2)
 
m3 <- diag(5)
m3[3, 3] = 42
m3
solve(m3)
A matrix: 2 × 2 of type dbl
22
32
A matrix: 2 × 2 of type dbl
-1.0 1
1.5-1
A matrix: 5 × 5 of type dbl
10000
01000
00100
00010
00001
A matrix: 5 × 5 of type dbl
10000
01000
00100
00010
00001
A matrix: 5 × 5 of type dbl
10 000
01 000
004200
00 010
00 001
A matrix: 5 × 5 of type dbl
100.0000000000
010.0000000000
000.0238095200
000.0000000010
000.0000000001

Datové rámce

Jedná se o velmi důležitý datový typ používaný zejména (ale nejenom) při statistických výpočtech. Datové rámce se v určitém ohledu podobají tabulkám používaným v relačních databázích: jednotlivé sloupce jsou pojmenované a současně může být každý sloupec jiného datového typu (všechny prvky ve sloupci toto kritérium musí splňovat). Tato vlastnost odlišuje datové rámce jak od dvojdimenzionálních polí, tak i od matic. S datovými rámci se ovšem nepracuje pouze v jazyku R; nalezneme je například i v knihovně Pandas určenou pro programovací jazyk Python. Datové rámce a operace s nimi jsou pochopitelně popsány v dokumentaci programovacího jazyka R. Příkladem může být dokumentace ke konstruktoru datových rámců:

Konstrukce datového rámce

In [21]:
ids = c(1:9)
names = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R")
usages = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37)
changes = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
In [22]:
languages <- data.frame(
    ids,
    names,
    usages,
    changes
)
 
languages
A data.frame: 9 × 4
idsnamesusageschanges
<int><chr><dbl><dbl>
1C 15.95 0.74
2Java 13.48-3.18
3Python 10.47 0.59
4C++ 7.11 1.48
5C# 4.58 1.18
6Visual Basic 4.12 0.83
7JavaScript 2.54 0.41
8PHP 2.49 0.62
9R 2.37 1.33
In [23]:
languages2 <- data.frame(
    id = ids,
    name = names,
    usage = usages,
    change = changes
)
 
languages2
A data.frame: 9 × 4
idnameusagechange
<int><chr><dbl><dbl>
1C 15.95 0.74
2Java 13.48-3.18
3Python 10.47 0.59
4C++ 7.11 1.48
5C# 4.58 1.18
6Visual Basic 4.12 0.83
7JavaScript 2.54 0.41
8PHP 2.49 0.62
9R 2.37 1.33

Neexistující hodnoty ve vstupních datech

In [24]:
ids = c(1:9)
names = c("C", "Java", "Python", "C++", "C#", "Visual Basic", NA, "PHP", "R")
usages = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, NA, 2.49, 2.37)
changes = c(0.74, NA, 0.59, 1.48, 1.18, 0.83, 0.41, NA, 1.33)
In [25]:
languages3 <- data.frame(
   id = ids,
   name = names,
   usage = usages,
   change = changes
)
 
languages3
A data.frame: 9 × 4
idnameusagechange
<int><chr><dbl><dbl>
1C 15.950.74
2Java 13.48 NA
3Python 10.470.59
4C++ 7.111.48
5C# 4.581.18
6Visual Basic 4.120.83
7NA NA0.41
8PHP 2.49 NA
9R 2.371.33

Výpočet a výpis statistických informací o datovém rámci

In [26]:
languages <- data.frame(
   id = c (1:9), 
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37), 
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33),
   stringsAsFactors = FALSE
)
 
summary(languages)
       id        name               usage            change       
 Min.   :1   Length:9           Min.   : 2.370   Min.   :-3.1800  
 1st Qu.:3   Class :character   1st Qu.: 2.540   1st Qu.: 0.5900  
 Median :5   Mode  :character   Median : 4.580   Median : 0.7400  
 Mean   :5                      Mean   : 7.012   Mean   : 0.4444  
 3rd Qu.:7                      3rd Qu.:10.470   3rd Qu.: 1.1800  
 Max.   :9                      Max.   :15.950   Max.   : 1.4800  

Konverze datového rámce na matici

V dalším demonstračním příkladu si ukážeme jednu poměrně často prováděnou operaci – konverzi datového rámce na „obyčejnou“ matici. To pochopitelně není zcela bezproblémové, protože všechny prvky matice musí být stejného datového typu. Pokud jsou řetězce reprezentovány formou faktorů, budou převedeny na celá čísla (indexy):

In [27]:
languages <- data.frame(
   id = c(1:9),
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37),
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
)
 
languages
 
 
m <- data.matrix(languages)
class(m)
m
A data.frame: 9 × 4
idnameusagechange
<int><chr><dbl><dbl>
1C 15.95 0.74
2Java 13.48-3.18
3Python 10.47 0.59
4C++ 7.11 1.48
5C# 4.58 1.18
6Visual Basic 4.12 0.83
7JavaScript 2.54 0.41
8PHP 2.49 0.62
9R 2.37 1.33
  1. 'matrix'
  2. 'array'
A matrix: 9 × 4 of type dbl
idnameusagechange
1115.95 0.74
2413.48-3.18
3710.47 0.59
43 7.11 1.48
52 4.58 1.18
69 4.12 0.83
75 2.54 0.41
86 2.49 0.62
98 2.37 1.33

Datový rámec získaný z matice – jednoduchý kalendář

In [29]:
m <- matrix(
  month.abb[c(12, 1:11)],
  nrow = 3,
  dimnames = list(
    c("start", "middle", "end"),
    c("Winter", "Spring", "Summer", "Fall")
  )
)
 
class(m)
m
 
df <- as.data.frame(m)
class(df)
df
  1. 'matrix'
  2. 'array'
A matrix: 3 × 4 of type chr
WinterSpringSummerFall
startDecMarJunSep
middleJanAprJulOct
endFebMayAugNov
'data.frame'
A data.frame: 3 × 4
WinterSpringSummerFall
<chr><chr><chr><chr>
startDecMarJunSep
middleJanAprJulOct
endFebMayAugNov

Datové rámce a grafy

Sloupcový graf s hodnotami vyčtenými z datového rámce

In [30]:
languages <- data.frame(
   id = c(1:9),
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37),
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
)
 
barplot(languages$usage)

Přidání popisku horizontální osy do grafu

In [31]:
languages <- data.frame(
   id = c(1:9),
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37),
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
)
 
barplot(languages$usage, names.arg=languages$name)

Úprava stylu zobrazení grafu

In [32]:
languages <- data.frame(
   id = c(1:9),
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37),
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
)
 
barplot(languages$usage, names.arg=languages$name,
     cex.axis = 0.8,
     cex.names = 0.6,
     las=2)

Přidání liniového grafu do grafu sloupcového

In [33]:
languages <- data.frame(
   id = c(1:9),
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37),
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
)
 
plt <- barplot(languages$usage, names.arg=languages$name,
     cex.axis = 0.8,
     cex.names = 0.6,
     las=2)
 
lines(plt, languages$change, type="o", col="red")

Sloupcový graf se dvěma skupinami sloupců

In [34]:
languages <- data.frame(
   id = c(1:9),
   name = c("C", "Java", "Python", "C++", "C#", "Visual Basic", "JavaScript", "PHP", "R"),
   usage = c(15.95, 13.48, 10.47, 7.11, 4.58, 4.12, 2.54, 2.49, 2.37),
   change = c(0.74, -3.18, 0.59, 1.48, 1.18, 0.83, 0.41, 0.62, 1.33)
)
 
data=t(languages[, c("usage", "change")])
print(data)
 
barplot(data, names.arg=languages$name,
     ylim=c(-5, 20),
     cex.axis = 0.8,
     cex.names = 0.6,
     las=2,
     beside=T)
        [,1]  [,2]  [,3] [,4] [,5] [,6] [,7] [,8] [,9]
usage  15.95 13.48 10.47 7.11 4.58 4.12 2.54 2.49 2.37
change  0.74 -3.18  0.59 1.48 1.18 0.83 0.41 0.62 1.33

Grafy průběhů funkcí

In [38]:
x <- 1:100
y <- sin(x/10)
plot(x,y)
In [39]:
plot(sin, from=0, to=2*pi)
In [40]:
n <- 1000
hist(sin(1:n * 2*pi/n))

Knihovna ggplot2

In [24]:
install.packages("ggplot2")
Installing package into ‘/usr/lib64/R/library’
(as ‘lib’ is unspecified)

Updating HTML index of packages in '.Library'

Making 'packages.html' ...
 done

In [25]:
x <- 1:6  # Create vector.
y <- x^2  # Create vector by formula.
model <- lm(y ~ x)
print(model)
Call:
lm(formula = y ~ x)

Coefficients:
(Intercept)            x  
     -9.333        7.000  

In [26]:
summary(model)
Call:
lm(formula = y ~ x)

Residuals:
      1       2       3       4       5       6 
 3.3333 -0.6667 -2.6667 -2.6667 -0.6667  3.3333 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -9.3333     2.8441  -3.282 0.030453 *  
x             7.0000     0.7303   9.585 0.000662 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.055 on 4 degrees of freedom
Multiple R-squared:  0.9583,	Adjusted R-squared:  0.9478 
F-statistic: 91.88 on 1 and 4 DF,  p-value: 0.000662
In [27]:
plot(model)

Typy vykreslení úseček

In [41]:
plot(0, xlim=c(1,7), ylim=c(1,6))
 
abline(h=1, lwd=1, lty=1, col="black")
abline(h=2, lwd=1, lty=2, col="blue")
abline(h=3, lwd=1, lty=3, col="cyan")
abline(h=4, lwd=1, lty=4, col="green")
abline(h=5, lwd=1, lty=5, col="orange")
abline(h=6, lwd=1, lty=6, col="red")

Regresní přímka v diagramu

In [42]:
input <- mtcars
 
plot(x = input$wt,y = input$mpg,
   xlab = "Weight",
   ylab = "Mileage",
   main = "Weight vs Mileage",
   pch=20, col="red"
)
 
text(input$wt+0, input$mpg+0.7, rownames(input), cex=0.2)
 
abline(20,0,col='blue', lty=2, lwd=1)
abline(25,0,col='darkgreen', lty=2, lwd=1)
 
regression <- lm(input$mpg~input$wt)
abline(reg=regression, col='lightblue', lwd=2)

Zakreslení statistických hodnot (průměru, směrodatné odchylky) do diagramu

In [43]:
input <- mtcars
 
plot(x = input$wt,y = input$mpg,
   xlab = "Weight",
   ylab = "Mileage",
   main = "Weight vs Mileage",
   pch=20, col="red"
)
 
text(input$wt+0, input$mpg+0.7, rownames(input), cex = 0.2)
 
abline(h = mean(input$mpg), col = '#ff8080', lwd = 1, lty = 2)
 
abline(h = mean(input$mpg) + sd(input$mpg), col = 'steelblue', lwd = 1, lty = 2)
abline(h = mean(input$mpg) - sd(input$mpg), col = 'steelblue', lwd = 1, lty = 2)
 
regression <- lm(input$mpg~input$wt)
abline(reg=regression, col='lightblue', lwd=2)