Kurzusok
/
R
R
/
Tanterv
/
Mátrixok és tömbök
Má

Mátrixok és tömbök ebben a kurzusban: R

{one: "1 feladat", other: "%{count} feladat"}

A(z) Mátrixok és tömbök fogalomról

Amikor homogén, atomos adatok gyűjteményeivel dolgozol (például csupa szám vagy csupa karakter), a következő adatszerkezetek állnak rendelkezésre R-ben:

  • vector egydimenziós adatokhoz, egyetlen indexszel érhető el.
  • matrix kétdimenziós, téglalap alakú (nem szaggatott) adatokhoz.
  • array az általános N-dimenziós esethez. A matrix valójában csak egy array, ahol N=2.
Note

Python-programozóknak: Ez a rész ismerősnek tűnhet.

A NumPy-val való bármilyen hasonlóság nem véletlen (az R viszont valamivel régebbi, és mindez az alapnyelvében megtalálható).

Mátrixok

A mátrix lényegében egy vektor, kiegészítve a sorok és oszlopok számával, amelyek meghatározzák az alakját.

Létrehozásukra van egy matrix() függvény:

# data already available 
matrix(1:6, nrow=2, ncol=3)
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6

# empty matrix to be filled in later
matrix(nrow=2, ncol=3)
#>      [,1] [,2] [,3]
#> [1,]   NA   NA   NA
#> [2,]   NA   NA   NA

Fontos, hogy az adatok oszlopfolytonos sorrendben tárolódnak (azaz előbb lefelé, aztán jobbra). Ez ugyanaz, mint a Fortranban, a Matlabban és a Juliában, de eltér a C/C++-tól és a NumPy-tól.

A mátrix méreteit a dim() függvénnyel kérdezheted le, ami megadja a sorok és az oszlopok számát is; egyetlen méretet a nrow() vagy a ncol() ad vissza. A length() csak a mögöttes vektor hosszát adja vissza: az elemek teljes számát (a fenti példában 6-ot).

Néhány más függvény is mátrixot ad eredményül, például a str_split_fixed().

library(stringr)

str_split_fixed(c("split some words", "and some more"), " ", 3)
#>      [,1]    [,2]   [,3]   
#> [1,] "split" "some" "words"
#> [2,] "and"   "some" "more" 

Mátrixindexelés

Ez pontosan ugyanúgy működik, mint a vektorok indexelése, csak itt meg kell adnod a sort (sorokat) és az oszlopot (oszlopokat), mégpedig ebben a sorrendben. Ha egy dimenziót üresen hagysz, a teljes sort vagy oszlopot kapod meg.

Ugyanazt a mátrixot használva, mint fent:

m <- matrix(1:6, nrow=2, ncol=3)
m
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6

m[2, 3]    # row 2, col 3
#> [1] 6

m[1:2, 3]  # rows 1:2, col 3
#> [1] 5 6

 m[2, ]    # all of row 2
#> [1] 2 4 6

Figyeld meg, hogy ha egy részhalmazban csak egyetlen sor és/vagy oszlop van, akkor az vektorként tér vissza, nem mátrixként.

class(m)
#> [1] "matrix" "array" 
class(m[2,])
#> [1] "integer"

Ez a fajta dimension reduction nem mindig kívánatos, különösen egy olyan függvényláncban, amely mátrix bemeneteket vár.

Ha megadod a drop=FALSE értéket, az garantálja, hogy mátrix bemenetből mátrix legyen a visszatérési érték. Figyeld meg, hogy az egysoros vagy egyoszlopos mátrix nem ugyanolyan típusú, mint egy vektor.

m[2, , drop = FALSE]
#>      [,1] [,2] [,3]
#> [1,]    2    4    6

Az as.matrix() függvény vektort alakít egyoszlopos mátrixszá.

as.matrix(1:3)
#>      [,1]
#> [1,]    1
#> [2,]    2
#> [3,]    3

A vektorokhoz hasonlóan a mátrix egyes részeit is egyszerűen módosíthatod új értékek hozzárendelésével.

m[, 2] <- c(10, 20)
m
#>      [,1] [,2] [,3]
#> [1,]    1   10    5
#> [2,]    2   20    6

Sorok és oszlopok hozzáadása és törlése

Vektoroknál elég volt a c() függvény ahhoz, hogy adatot beszúrj vagy hozzáfűzz. A mátrixok szerkezete összetettebb, ezért körültekintőbben kell megadnod, mire van szükség.

Az rbind() és a cbind() függvény új sort vagy oszlopot fűz a mátrixhoz.

m
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6
m2 <- matrix(7:9, nrow = 1, ncol = 3)

rbind(m, m2)
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6
#> [3,]    7    8    9

Egy sor vagy oszlop törléséhez negatív indexelést használsz, ahogy a vektoroknál.

m
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6

m[, -2]
     #> [,1] [,2]
#> [1,]    1    5
#> [2,]    2    6

Szűrés és függvények

Minden vektoros függvény működik mátrixokon is, az összes elemre alkalmazva. Csakhogy elveszíthetik a mátrix szerkezetét, és vektort adnak vissza.

sqrt(m)
#>          [,1]     [,2]     [,3]
#> [1,] 1.000000 1.732051 2.236068
#> [2,] 1.414214 2.000000 2.449490

sum(m)
#> [1] 21

m[m > 3]
#> [1] 4 5 6

Mátrixoknál ezen kívül hasznos lehet a colSums() és a rowSums() függvény.

Ebben az esetben a dimenziócsökkentés szándékos, ezért a visszatérési értékek vektorok.

# m as defined above
rowSums(m)
#> [1]  9 12
colSums(m)
#> [1]  3  7 11

Hasonlóképpen léteznek rowMeans() és colMeans() függvények az átlagok kiszámítására.

Általános függvények mátrixokon

Más fogalmaknál láttuk, hogy a Tidyverse könyvtárai leegyszerűsíthetik a vektorokon és listákon (purrr) vagy adattáblákon (dplyr) végzett műveleteket.

A mátrixok és a tömbök azonban nagyrészt kívül esnek a Tidyverse bemeneteinek körén (legalábbis egyelőre).

Az apply() függvény a Base R része, és továbbra is ez a legjobb eszköz, ha finomabb irányítást szeretnél a mátrixprogramozás felett.

A paraméterek sorrendben a következők:

  1. A bemeneti mátrix.
  2. A dimenzió, amelyen a műveletet végezni szeretnéd (1 a sorokhoz, 2 az oszlopokhoz).
  3. Az alkalmazni kívánt függvény.
  4. Opcionálisan a függvény további paraméterei.

A rowMeans() függvény megtalálható a Base R-ben, de apply() és mean() segítségével mi magunk is utánozhatjuk.

randm <- sample(1:10, 16, replace = TRUE) |> matrix(4, 4)
randm
#>      [,1] [,2] [,3] [,4]
#> [1,]    4    9    8    3
#> [2,]    6    8    5    5
#> [3,]    4    2    1    2
#> [4,]    4    2    5    4

apply(randm, 1, mean)
#> [1] 6.00 6.00 2.25 3.75

rowMeans(randm)
#> [1] 6.00 6.00 2.25 3.75

Lineáris algebra

Note

Ez a rész az Exercism hatókörén kívül eső szintű matematikai ismereteket feltételez.

Nyugodtan hagyd ki, ha semmit nem értesz belőle.

Az R viszont adattudományi nyelv, és sok felhasználó jártas az alkalmazott matematikában és a statisztikában. Ez a tömör összefoglaló néhány tanulónak érdekes lehet.

A modern R „nyilvánvalóan” adattudományi nyelv: elsősorban táblázatos adatokkal való munkára tervezték, és népszerű olyan felhasználók körében, mint a statisztikusok, az epidemiológusok és a társadalomtudósok. Ezen a területen a fő versenytárs a Python tudományos ökoszisztémája, olyan csomagokkal, mint a Pandas vagy a Polars.

A korábbi évtizedekben azonban az R-t potenciális mérnöki nyelvként is számon tartották, amely közvetlenül a Matlabbal versenyzett.

Bármilyen meglepő, a Base R a mai napig támogatja a lineáris algebrai műveletek teljes skáláját vektorokon és mátrixokon. Nem világos, hogy ezek ma mennyire jelennek meg a felhasználói kódban, de az ilyen technikák belsőleg továbbra is nagyon fontosak a statisztikai függvények megvalósításához.

Az R lineáris algebráját még mindig tanítják néhány egyetemi kurzuson, például ezen az ökonometriaórán. A matematikához (nem a programozáshoz) jó útmutatót találsz a 3Blue1Brown csatornán.

Advanced

Az Exercism-ön belül a lineáris algebra legteljesebb tárgyalása a Julia tantervében található (ugyanazok a szerzők, mint az R tantervét).

Úgy gondoljuk, hogy a komoly lineáris algebrai munkához ma a Julia (vagy a Python ott, ahol a numpy.linalg modul elérhető) megfelelőbb nyelv lenne, mint az R.

Átlók

Egy négyzetes (N x N)) A mátrix főátlója a bal felső saroktól (A[1,1]) a jobb alsóig (A[N,N]) tart.

A diag() függvény viselkedése attól függ, milyen argumentumot adsz át neki.

Egy v vektor esetén a diag(v) átlós mátrixot hoz létre.

diag(1:3)
#>      [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    0    2    0
#> [3,]    0    0    3

Egy négyzetes A mátrix esetén a diag(A) a főátlón lévő elemeket adja vissza vektorként.

A
#>      [,1] [,2] [,3]
#> [1,]   10    5    2
#> [2,]    9    3    7
#> [3,]    8   10    4
diag(A)
#> [1] 10  3  4

Egyetlen k egész szám esetén a diag(k) egy k × k egységmátrixot hoz létre: talán nem erre számítottál.

Még a komoly R-tankönyvek is hajlamosak ilyen megjegyzéseket fűzni ilyenkor: „Ki érti ezt?”.

diag(3)
#>      [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    0    1    0
#> [3,]    0    0    1

Transzponálás és inverz

A sorok és oszlopok felcseréléséhez a t() függvény bármely mátrixot transzponál.

m
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6
t(m)
#>      [,1] [,2]
#> [1,]    1    2
#> [2,]    3    4
#> [3,]    5    6

Komplex értékű mátrix esetén az eredmény nem a komplex konjugált. A Conj(t(A)) hívással kapod meg az A mátrix konjugált transzponáltját (adjungáltját).

Magasabb dimenziós tömböknél az aperm() permutálja a dimenziókat.

Egy négyzetes A mátrix inverzéhez a solve(A) függvényt használhatjuk. Néhányunk szerint ez a szintaxis ... meglepő.

Ha egy mátrixot megszorzunk az inverzével, az egységmátrixot kapjuk (apró kerekítési hibáktól eltekintve).

A <- matrix(sample(1:10, 9, replace = TRUE), 3, 3)
A
#>      [,1] [,2] [,3]
#> [1,]   10    5    2
#> [2,]    9    3    7
#> [3,]    8   10    4

solve(A)
#>             [,1]        [,2]        [,3]
#> [1,]  0.16666667  0.00000000 -0.08333333
#> [2,] -0.05747126 -0.06896552  0.14942529
#> [3,] -0.18965517  0.17241379  0.04310345

A %*% solve(A) |> round(digits = 10)
     [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    0    1    0
#> [3,]    0    0    1

Szorzás

A szokásos aritmetikai operátorok, mint a +, -, *, ^, elemenként működnek a mátrixokon. Ha a dimenziók nem egyeznek, az újrahasznosítás szokásos szabályai érvényesek.

m
#>      [,1] [,2] [,3]
#> [1,]    1    3    5
#> [2,]    2    4    6

m * m
#>      [,1] [,2] [,3]
#> [1,]    1    9   25
#> [2,]    4   16   36

# same calculation, different syntax
m ^ 2
#>      [,1] [,2] [,3]
#> [1,]    1    9   25
#> [2,]    4   16   36

A vektor- és mátrixszorzás egyéb fajtáinak bemutatása meghaladja a kereteinket, de íme egy nagyon rövid összefoglaló:

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg