Kodas
{
ABC <- character(10)
ABC[1] <- "tekstas"
ABC[1:3]
}
#> [1] "tekstas" "" ""Reikėtų konspekto pradžioje įterpti sąvoka išraiška, su pavyzdžiais.
Dažnai rašant R kodą, veiksmų eiga ir vykdymas priklauso nuo sąlygų ar pasikartojančių veiksmų. Sąlyginių logikų ir ciklų rašymas yra fundamentalūs bet kokiai programavimo kalbai, įskaitant ir R.
Šiame skyriuje dažnai naudosime kodo blokų konstrukciją, kuri žymima riestiniais skliaustais {}. Komandas, užrašytas šiuose skliaustuose, R supranta kaip vieną komandą. Ši savybė leidžia apjungti daugybę komandų, kad jos būtų vykdomos kartu.
Pavyzdžiui, inicializuosime character tipo vektorių iš 10 elementų, priskirsime pirmajam elementui reikšmę ir išvesime į konsolę pirmus tris elementus.
{
ABC <- character(10)
ABC[1] <- "tekstas"
ABC[1:3]
}
#> [1] "tekstas" "" ""Tokį bloką galima interpretuoti kaip dar vieną išraišką, kurios reikšmė yra paskutinė bloko viduje esančios išraiškos rezultatas. Galima įsitinkti tuo priskiriant bloko grąžinamą reikšmę kintamajam.
a <- {
ABC <- character(10)
ABC[1] <- "tekstas"
ABC[1:3]
}
a
#> [1] "tekstas" "" ""Skliaustuose {} užrašytos išraiškos rezultatas išvedamas į konsolę tik tada, jei jis nepriskiriamas kintamajam.
Kokia bus kintamojo a reikšmė įvykdžius šią komandą?
a <- {
ABC <- character(10)
ABC[1] <- "tekstas"
}Tušti riestieniai skliaustai prilygsta NULL objektui.
b <- {}
b
#> NULLKita rūšis skliaustų, paprastieji skliaustai (), kaip ir kitų tipų skliaustai, R kalboje suprantami tarsi funkcijos. Jie turi dvi pagrindines užduotis. Pirma, sugrupuoja skliaustų viduje esančią išraišką ir leidžia valdyti veiksmų vykdymo eiliškumą. Antra, išraiška (x) yra ekvivalenti funkcijai \(f(x) = x\). Kadangi funkcijos reikšmė automatiškai išvedama į konsolę, tai skliaustuose užrašytos išraiškos reikšmė taip pat išvedama į konsolę. Dėl šios savybės skliaustai patogūs „vienu ypu“ ir priskirti reikšmę, ir ją parodyti:
(b <- 2+2)
#> [1] 4if-else
Sąlyginis komandų vykdymas dažnai naudojamas skaičiavimuose, kai tam tikri veiksmai priklauso nuo tikrinamų sąlygų. Tam naudojama tikrinimu konstrukcija if-else. Bendra sintaksė atrodo taip:
if (loginė sąlyga) {
israiškos A
} else {
išraiškos B
}Loginės sąlygos rezultatas turi būti vieną loginį elementą turintis vektorius. Sąlygos rezultatas negali būti NA reikšmė. Jei sąlygos vektorius turi daugiau nei vieną elementą, tikrinama tik pirmojo elemento reikšmė. Jei sąlygos reikšmė yra TRUE, tai vykdoma pirmojo bloko dalis, jei FALSE - antrojo bloko.
Paprastas if-else pavyzdys.
Jei išraiškas riestiniuose skliaustuos galima užrašyti kaip vieną komandą, tai skliaustų {} galima ir nenaudoti. Tokiu atveju, if-else sutrumpėja iki vienos eilutės.
if (loginė sąlyga) išraiška A else išraiška BTas pats pavyzdys, šiuo atveju supaprastintas.
Antroji, else{}, dalis nėra būtina. Tokiu atveju naudojama supaprastinta if konstrukcija.
if (loginė sąlyga) {
išraiškos A
}Pavyzdžiui, turime du skaitinius kintamuosius a ir b. Kintamojo a reikšmė turi būti mažesnė už b reikšmę. Jeigu taip nėra, reikia juos sukeisti vietomis.
a <- 6
b <- 1
if (a > b) {
t <- a
a <- b
b <- t
rm(t)
}Konstrukcija if-else gali veikti kaip funkcija, t.y. grąžinti reikšmę, todėl ją galima rašyti kaip vieną išraišką ir iš karto priskirti kintamajam:
v <- if (sąlyga) reiškinys1 else reiškinys2Kitaip tariant, v įgis reikšmę reiškinys1, jei sąlyga tenkinama, ir reiškinys2, jei ne. Tai leidžia kompaktiškiau užrašyti komandas.
Be šios galimybės, naudojant įprastą if-else konstrukciją, kodas atrodytų taip:
if (sąlyga) {
v <- reiškinys1
} else {
v <- reiškinys2
}Žinoma, kompaktiškumas neturi nustelbti kodo skaitomumo. Jei reiškinys1 ar reiškinys2 sudėtingi (pvz. kviečia funkcijas), įsitikinkite, kad vienos eilutės versija vis dar aiškiai suprantama. Jeigu ne, galima objektui priskirti reikšmę naudojant pilną if-else konstrukciją.
v <- if (sąlyga) {
išraiškos A
} else {
išraiškos B
}ifelse()
Tuo atveju, kai vektoriaus elementui priskiriama arba viena, arba kita reikšmė, priklausomai nuo to, ar kito vektoriaus elementas tenkina sąlyga, naudojama funkcija ifelse(), dar vadinama vektorizuotu if. Funkcijos sintaksė paprasta.
ifelse(loginis vektorius, taip, ne)Loginių reikšmių vektorius gali būti bet kokio ilgio, įprastai tai loginės sąlygos apie vektoriaus elementus rezultatas.
Funkcija naudinga tuo, kad elementų priskyrimui pagal sąlygas nereikia ciklo.
Pavyzdžiui, vektoriui m priskirsime reikšmę 1, jei vektoriaus n elementas yra lyginis, ir reikšmę -1, jei - nelyginis.
Kintamojo egzistavimui nustatyti naudojama funkcija exists(). Naudodami šią funkciją, užrašykite komandą, kuri patikrina, ar egzistuoja kintamasis X, ir, jei tokio kintamojo nėra, į konsolę išvedamas tekstinis pranešimas.
Naudojant funkciją ifelse(), užrašykite komandą, kuri NA reikšmę turintiems vektoriaus c(1, 2, NA, 4, 5, NA, NA, 8) elementams priskiria reikšmę 0. Užrašykite analogišką komandą nenaudojant funkcijos ifelse().
Turime temperatūrų matavimų vektorių c(-2, 4, 11, 17, 22, 29, 14, 7). Parašykite vieną ifelse() komandą, kuri vektoriui žyma suteikia reikšmę “šalta”, kai temperatūra mažiau už 5, reikšmę normalu, kai temperatūra tarp 5 ir 20 (neįskaitant), ir reikšmę karšta, kai temperatūra viršija 20.
Užrašykite komandą, kuri patikrina, ar visų vektoriaus c(1, 5, 0, 8, 8, 6, 1) elementų reikšmės neviršija 5. Jei ši sąlyga teisinga, tai kinamajam k priskiriama reikšmė 0. Jei sąlyga netenkinama, kintamajam k priskiriamas didesnių už 5 vektoriaus elementų skaičius, o kintamajam l priskiriamas bendras pradinio vektoriaus elementų skaičius.
Užrašykite komandą, kuri patikrintų, ar vektorius c(pi, 2, 3.5) yra sveikųjų skaičių vektorius. Jei ne, vektoriaus klasę pakeiskite į sveikųjų ir į konsolę išveskite pranešimą apie vektoriaus klasės pakeitimą.
Programavime ciklai naudojami algoritmuose, kur atliekami tam tikri pasikartojantys veiksmai. Jų skaičius gali būti iš anksto žinomas arba keistis priklausomai nuo ciklo metu tikrinamų sąlygų.
for
Ciklas for naudojamas tais atvejais, kai veiksmų pakartojimų (iteracijų) skaičius iš anksto žinomas. Bendra ciklo for konstrukcija atrodo taip:
for (var in set) {
išraiškos
}Kintamasis var įgyja reikšmes iš aibės set. Ši aibė gali būti sudaryta iš vektoriaus elementų numerių (indeksų), matricos eilučių ar stulpelių numerių, taip pat vardų, kodų ar kitų kintamųjų, kurių reikšmes turi įgyti ciklo kintamasis (iteratorius) var. Aibė set nebūtinai turi apimti visus vektoriaus elementus, be to, elementai gali būti išdėstyti bet kokia tvarka, jie gali kartotis ir t.t.
Pavyzdžiui, naudodami ciklą for, apskaičiuosime vektoriaus elementų sumą.
Iš eilės einančių vektoriaus arba sąrašo elementų indeksų aibę galima gauti naudojant funkciją seq_along().
# 1:length(v) = seq_along(v)
suma <- 0
for (i in seq_along(v)) {
suma <- suma + v[i]
}
suma
#> [1] 208Kadangi ciklo kintamasis turi perbėgti per visų vektoriaus elementų indeksus, o ciklo viduje naudojamos vektoriaus elementų reikšmės, vietoje indeksų aibės galima nurodyti patį vektorių.
suma <- 0
for (i in v) {
suma <- suma + i
}
suma
#> [1] 208Tarkim, kad vektoriaus elementų reikšmės gautos vienodais laiko intervalais matuojant tam tikrą kintantį dydį. Toks vektorius vadinamas laiko eilute. Statistikoje dažnai taikomas laiko eilutės glodinimas slenkančiu vidurkiu. Sudarykite vektorių, kurio pirmojo elemento reikšmė būtų lygi vektoriaus v <- c(19, 5, 2, 19, 29, 42, 32, 35, 25, 55, 24, 11, 18) 1, 2 ir 3 elementų vidurkiui, antro elemento reikšmė - 2, 3, ir 4 elementų vidurkiui ir taip toliau iki galo.
Užrašykite algoritmą, kuris surastų didžiausią reiškmę turintį vektoriaus v elementą ir nustatytų jo eilės numerį.
Naudodami ciklą for, sudarykite vektorių, kurio elementai lygūs matricos \(M\) eilučių sumoms. \[\begin{equation*}
M = \begin{pmatrix}
2 & 3 & 4 & 5 & 6 \\
3 & 4 & 5 & 6 & 7 \\
4 & 5 & 6 & 7 & 8 \\
5 & 6 & 7 & 8 & 9
\end{pmatrix}
\end{equation*}\]
Naudodami ciklą for, užrašykite algoritmą natūrinio skaičiaus \(n\) faktorialui apskaičiuoti.
while
Ciklas while naudojamas tada, kai tam tikrus pasikartojančius veiksmus reikia kartoti tol, kol tenkinama sąlyga. Bendra ciklo while konstrukcija atrodo taip:
while (loginė sąlyga) {
išraiškos
}Ciklas neturi būti amžinai besitęsiantis - tam tikru momentu loginės sąlygos reikšmė privalo tapti FALSE.
Paprastas tokio tipo ciklo pavyzdys.
i <- 1
while (i <= 10) {
i <- i+4
}
i
#> [1] 13Kartais ciklą reikia nutraukti dėl tam tikrų susidariusių sąlygų. Bet kokio tipo ciklui nutraukti naudojamos dvi komandos: next ir break. next nutraukią dabartinę iteraciją ir ciklas iš naujo vykdomas su sekančia iteracija, o break nutraukia ciklą ir išeina iš jo.
Praėjusio kodo pavyzdys, dabar naudojant break komandą.
i <- 1
while (TRUE) {
i <- i+4
if (i > 10) break
}
i
#> [1] 13Pavyzdžiui, galime išnaudoti komandą next spausdinant tik nelyginius skaičius iki 15. Vadinasi, kai išvedamas skaičius į konsolę bus lyginis, jį reikia praleisti.
Naudodami ciklą while, apskaičiuokite, kiek iš eilės einančių vektoriaus v elementų reikia susumuoti, norint gauti didžiausią sumą neviršijančią 100. Loginę sąlygą reikia užrašyti taip, kad susumavus visus elementus, bet sumai neviršijus 100, ciklas būtų nutraukiamas.
Naudodami ciklą while, užrašykite vektoriaus elementų išrikiavimo priešinga tvarka algoritmą.
repeat
Ciklo repeat veikimas ir principas yra panašus į ciklą while, tačiau nutraukimo sąlyga tikrinama ciklo viduje naudojant komandą break. Bendra konstrukcija atrodo taip:
repeat {
išraiškos
if (loginė sąlyga) break
}Pavyzdžiui, užrašysime algoritmą, kuris skaičiavimus nutraukia po tam tikro laiko tarpo. Šiuo atveju tai bus 1 dešimtoji sekundės. Į konsolę bus išvedamas iteracijos numeris.
start.time <- proc.time()
i <- 0
repeat {
i <- i + 1
cat(i, "\n")
flush.console()
laikas <- proc.time()[3] - start.time[3]
if (laikas > 0.1) break
}