1 Instrukcje warunkowe ifelse

W języku R, podobnie jak w większości języków programowania, mamy możliwość korzystania z instrukcji warunkowych. Umożliwia ona warunkowe wykonanie kodu w zależności od prawdziwości pewnego warunku logicznego. Jej składnia jest następująca

if(warunek logiczny){
  blok instrukcji 1
}

lub

if(warunek logiczny){
  blok instrukcji 1
} else{
  blok instrukcji 2
}

lub gdy potrzebujemy więcej warunków

if(warunek logiczny 1){
  blok instrukcji 1
} else if(warunek logiczny 2){
  blok instrukcji 2
} else if(warunek logiczny 3){
  blok instrukcji 3
} else{
  blok instrukcji 4
}

Na przykład

a <- 200
b <- 33
if (b > a) {
  print("b jest większe od a")
} else if (a == b) {
  print("a i b są równe")
} else {
  print("a jest większe od b")
} 
## [1] "a jest większe od b"

1.1 Zadania - instrukcje warunkowe

1.1.1 Zadanie

Zadanie z numerem PESEL.

Numer PESEL to jedenastocyfrowy symbol numeryczny, który pozwala na łatwą identyfikację osoby, która go posiada. Numer PESEL zawiera datę urodzenia, numer porządkowy, oznaczenie płci oraz liczbę kontrolną. (więcej szczegóły znajdziesz na stronie: PESEL_gov)

W zmiennej pesel zainicjuj wektor z jedenastu cyfr, które będą oznaczać numer PESEL.

Dla zadanego peselu napisz kod sprawdzający, czy jest on poprawny (odpowiednia długość i sprawdzenie liczby kontrolnej). Następnie, jeśli jest poprawny wypisz:

  • datę urodzenia,

  • płeć i wiek właściciela (bazując na dacie urodzenia),

jeżeli natomiast PESEL nie jest poprawny wypisz komunikat, że podany numer PESEL jest błędny.

Przykładowo:

  1. pesel = 02070803628, powinniśmy otrzymać:

[1] “PESEL jest poprawny!”

[1] “Numer PESEL należy do kobiety”

[1] “Data urodzenia: 0 8 - 0 7 - 19 0 2”

[1] “Wiek: 122”

  1. pesel = 98083454361, powinniśmy otrzymać:

[1] “Numer PESEL jest błędny”

Wywołaj swój kod dla podanych numerów PESEL:

  • c(8,4,0,7,2,1,3,8,2,6,9),

  • c(0,1,2,6,3,0,3,7,5,3,8),

  • c(8,1,0,2,0,5,2,7,3,5,8).

Wskazówka: Do wypisania tych informacji najwygodniej jest użyć funkcji paste() służącej do łączenia tekstu ze zmiennymi, jak w przykładzie:

a=runif(1) # Od random uniform, a nie run if!
paste('Liczba',a,'jest liczbą losową')
## [1] "Liczba 0.485669558634982 jest liczbą losową"

Wskazówka: operator %% dzielenia modularnego można wykorzystać do sprawdzenia parzystości liczby:

271%%2==0
## [1] FALSE
52%%2==0
## [1] TRUE

2 Pętle

Uwaga: W R należy unikać pętli, ponieważ są one ogólnie nieefektywne, ze względu na długie czasy obliczeń. Wynika to z faktu, że operacje wektorowe są zoptymalizowane na poziomie wewnętrznym i mogą korzystać z niskopoziomowych bibliotek matematycznych napisanych w językach takich jak C, co pozwala na bardziej efektywne zarządzanie pamięcią i procesorem. W poniższym kodzie porównamy wydajności operacji wykonywanych za pomocą pętli oraz operacji wektorowych w języku R, wykorzystując bibliotekę microbenchmark do pomiaru czasu wykonywania oraz ggplot2 do wizualizacji wyników.

library(microbenchmark)
library(ggplot2)
 
#instrukcje testowe
x=rnorm(1000) # losujemy 1000 liczb ze standardowego rozkładu normalnego
y1=numeric(1000) #alokacja pamięci na 1000 liczb
y2=numeric(1000) #j.w.
#test właściwy
pomiary1=microbenchmark( #funkcja microbenchmark 100 razy powtarza każdą testowaną instrukcję
petla = {for(i in 1:1000) y1[i]=sin(x[i])},  #obliczenie wartości f. sinus 1000x za pomocą pętli
wektorowe = {y2=sin(x)} #obliczenie f. sinus na wektorze o długości 1000
)
 
autoplot(pomiary1) #narysowanie wykresu

W pętli sinus jest obliczany dla każdej wartości wektora x i jest zapisywany w wektorze y1. Natomiast, w kolejnej linii, sinus jest obliczany dla całego wektora x naraz. W większości przypadków jest możliwa wektoryzacja obliczeń, aby uniknąć pętli. W przypadku bardziej skomplikowanych sytuacji można użyć też funkcji: outer, apply, lapply, tapply i mapply, aby wykonywać pętle bardziej efektywnie.

2.1 Pętla for

Ogólny schemat pętli for to:

for (iterator in kolekcja) {
  blok instrukcji
}

Prosty przykład pętli for:

x=NULL #inicjalizacja 
for(i in 1:10) #pętla będzie wykonywana dla i od 1 do 10
  {
  x[i]=i #
} #ciąg instrukcji kończymy nawiasem klamrowym
x #wypisanie wektora x
##  [1]  1  2  3  4  5  6  7  8  9 10

Po wykonaniu pętli w oknie Enviroment pojawia się zmienna o nazwie i o wartości 10L - litera L oznacza zmienną typu interger - całkowitą (32-bit).

Inny przykład wykorzystania pętli for

s=0
x=rnorm(10000) #generuje próbę 10.000 elementową ze standardowego rozkładu normalnego
for(i in 1:10000) #wykonanie pętli dla każdego elementu x od 1 do 10.000
{
  if(x[i]<10)
  {
    s=s+x[i]
  }   else
  {
    s=s+2*x[i]
  }
}
s
## [1] 110.6501

Powyższą pętlę można zastąpić wydajniejszym poleceniem:

sum(x[x<10])+2*sum(x[x>=10])
## [1] 110.6501

Inne przykłady

wekt=c(1,5,8,3,-2)
for(i in wekt) #pętla będzie wykonywana dla i z zadanego wektora `wekt`
  #- nie musi być on uporządkowany
  {
  print(i^2)
} #ciąg instrukcji kończymy nawiasem klamrowym
## [1] 1
## [1] 25
## [1] 64
## [1] 9
## [1] 4

2.2 Pętla while

Pętla while stanowi trochę bardziej elastyczne narzędzie, gdy liczba powtórzeń pętli nie jest ustalona. Ma następujący szablon:

while (warunek logiczny) {
  blok instrukcji
}

Przykład:

x=NULL #inicjalizacja
i=0 #inicjalizacja
while(i<10) # warunek stopu: blok instrukcji wykonywany jest tak długo, dopóki i <10
{ 
i=i+1 #bez tej instrukcji pętla while byłaby nieskończona
x[i]=i #instrukcja wewnątrz pętli
} #koniec pętli while
x #wypisanie wyniku
##  [1]  1  2  3  4  5  6  7  8  9 10

2.3 Pętla repeat

W przypadku pętli while (patrz powyższy przykład) konieczne jest zainicjalizowanie zmiennej i przed rozpoczęciem pętli. Można tego uniknąć używając pętli repeat, która ma następujący składnię

repeat {
  blok instrukcji
}

Zauważmy, że powyższa pętla będzie działać tak długo aż…. powiemy stop wykorzystując break Przykład:

x=NULL
i=1
repeat{
  x[i]=i
  if (i>=10){
    break #wyjście z pętli repeat gdy `i` osiągnie lub przekroczy wartość  10
  } #koniec if
  i=i+1 #właściwa instrukcja
} #koniec pętli repeat
x
##  [1]  1  2  3  4  5  6  7  8  9 10

2.4 Zadania - pętle

2.4.1 Zadanie

a. Napisz kod, który obliczającą \(n!\) (n silnia). Należy pamiętać o odpowiednich ograniczenia (klasyczną silnię liczymy dla liczb naturalnych łącznie z zerem). Może być to wersja rekurencyjną lub iteracyjna

b. Oblicz wartość \(n!\) dla wektora \([1,\ldots, 10]\) korzystając z wbudowanej funkcji factorial oraz apply w odpowiedniej wersji. Wynikiem powinien być wektor silni kolejnych liczb. Wskazówka: wynikiem lapply jest lista, więc aby dostać wektor można np. użyć unlist (sprawdź, jak działa w pomocy) lub inna wersja apply.

c. Napisz kod obliczającą wartość symbolu Newtona \({n \choose k}=\frac{n!}{k!(n-k)!}\) wykorzystującą funkcję factorial.

2.4.2 Zadanie

Wyjaśnić powód różnego działania dwóch podobnych pętli:

n=10
for(i in 1:n-4) #pętla będzie wykonywana dla i ... jakich?
  {
  print(i)
} 
## [1] -3
## [1] -2
## [1] -1
## [1] 0
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6

oraz

n=10
for(i in 1:(n-4)) #pętla będzie wykonywana dla i ... jakich?
  {
  print(i)
} 
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6

2.4.3 Zadanie

  1. Wygeneruj próbę 50-cio elementową \(x=(x_{1},…,x_{50})\) z rozkładu jednostajnego na przedziale \([0,1]\) używając funkcji runif()

  2. Utwórz wektor \(y=(y_1,\dots, y_{50})\), taki że \(y_i=0,\) gdy \(x_i<0.5\) wygenerowane w podpunkcie a. oraz \(y_i=1\) w przeciwnym przypadku za pomocą instrukcji if oraz, kolejno, pętli for, while i repeat.

3 Funkcje

Funkcje są to fragmenty kodu programu wywoływane w różnych miejscach z “niewielką” różnicą w argumentach. Pozwalają na uniknięcie duplikowania kodu, rozbicie kodu na mniejsze, łatwiejsze do zrozumienia części, uproszczenie programu i zwiększenie jego czytelności.

Schemat funkcji:

nazwa_funckji <- function(argumenty_po_przecinku){
  
  ciało funckji
  
  return(wartość_zwracana_przez_funkcję)
}

Najprostszy przykład funkcji (bez nazwy, nie jest ona wymagana):

function(a,b){
  a+b^2
} 
## function(a,b){
##   a+b^2
## }

to funkcja, która do pierwszego argumentu funkcji dodaje kwadrat drugiego. W nawiasach po słowie kluczowym function umieszcza się argumenty funkcji, po czym w nawiasach {…} znajduje się tak zwane ciało funkcji czyli zbiór instrukcji do wykonania przez funkcję.

W R funkcja jest zwykłym obiektem, takim jak liczba czy napis. Nawet gdy nie ma nazwy można ją wywołać za pomocą operatora () jak niżej:

(function(a,b){
  a+b^2}
 )(1,2)
## [1] 5

gdzie wywołujemy funkcję z argumentami a=1 oraz b=2.

3.1 Nazywanie funkcji

Zacznie prościej używa się funkcji, gdy ma ona nazwę. Aby nazwać funkcję przypisujemy ją do dowodnego wyrazu. Na przykład:

moja_funkcja <- function(a,b){
  a+b^2
} 

3.2 Argumenty i wartości

Funkcję mogą przekazywać (zwracać) wartości. Wtedy za wynik funkcji przyjmowana jest wartość wyznaczona w ostatniej linii ciała funkcji. Jeżeli potrzebne jest zwrócenie innych wartości, można skorzystać z polecenia return() z argumentami będącymi wartościami do zwrócenia.

Na przykład:

moja_funkcja2 <- function(a,b){
  c=a+b^2
  return(c^2)
} 

Funkcja nie musi mieć argumentów, na przykład funkcja

Sys.time()
## [1] "2024-10-29 20:30:44 CET"

zwraca aktualny czas.

Funkcje mogą mieć dowolną liczbę argumentów, każdy argument musi mieć unikalną nazwę. Do każdego argumentu możemy wskazać wartość domyślną, która będzie stosowana, jeśli dany argument nie zostanie użyty przy wywołaniu funkcji.

Przy wywołaniu funkcji można przez nazwę wskazać, który argument jest określany. Jeżeli wywołujemy funkcję z wartościami, ale bez podania nazw argumentów, to wartości będą przypisane do kolejnych argumentów, jak w poniższych przykładach:

moja_funkcja2 <- function(a=10,b=5){ # definiujemy funkcje z domyślnymi wartościami argumentów
  c=a+b^2
  return(c^2)
}
moja_funkcja2(3,2) # wywołanie funkcji moja_funkcja2, gdzie a=3 oraz b=2
## [1] 49
moja_funkcja2(3) # wywołanie funkcji moja_funkcja2, gdzie a=3 (bo pierwsze) oraz b=5 (domyślne)
## [1] 784
moja_funkcja2(b=7) # wywołanie funkcji moja_funkcja2, gdzie a=10 (domyślne) oraz b=7
## [1] 3481
moja_funkcja2() # wywołujemy funkcję z domyślnymi wartościami argumentów
## [1] 1225

3.3 Zmienne lokalne i globalne

Argumenty przekazywane są do funkcji poprzez wartości, wewnątrz funkcji zmienne są lokalne.

rm(n) #usuwa "n", o ile gdzieś się pojawiła taka zmienna
# a gdy n nie jest zadeklarowane to pojawia się warning: 
# Warning message:
#In rm(n) : object 'n' not found
y=5 #przypisanie wartości zmiennej "y"

power=function(x,n){ # nowa funkcja
  y=x^n
  return(y)
}
power(3,5) #wywołanie funkcji
## [1] 243
y # wartość "y" poza funkcją nie zmieniła się
## [1] 5

W czasie wykonywania funkcji przekazywana jest kopia argumentów, a funkcja nie zmienia wartości zmiennych dostępnych w środowisku pracy. Obiekty ze środowiska pracy mogą zostać wykorzystane przez funkcję:

rm(n) #usuwa "n", o ile gdzieś się pojawiła taka zmienna
power2=function(x){# n nie jest już argumentem
  y=x^n
  return(y)
}
power2(3) # wywołanie kończy się błędem
n=4 # tworzy globalnego "n"
power2(3) # wywołanie ma teraz sens, choć jakiś fragment kodu może tego "n" podmienić
## [1] 81

Powyższy sposób (korzystanie ze zmiennych globalnych) jest częstym źródłem błędów (nie tylko w R), bezpieczniej jest zadeklarować wszystkie zmienne wykorzystywane przez funkcję jako dane wejściowe.

3.4 Zwracanie więcej niż jednej wartości

Jeżeli zachodzi potrzeba, by funkcja zwracała więcej niż jedna wartość można posłużyć się listą lub wektorem (jeśli zwracane elementy są tego samego typu).

Na przykład:

moja_funkcja3 <- function(a=10,b=5){ # definiujmy funkcje z domyślnymi wartościami argumentów
  c=a+b^2
  return(c(c^2,c))
}
moja_funkcja3()
## [1] 1225   35

Poniższa funkcja jako argumenty przyjmuje długość n próby prostej z rozkładu normalnego o średniej sr i odchyleniu standardowym odch. Funkcja generuje wspomnianą próbę, oblicza średnią i odchylenie “empiryczne” wygenerowanej próbki, a następnie zwraca listę - trójkę: wygenerowaną próbę, jej średnią i odchylenie standardowe w postaci listy:

losuj=function(n=50,sr=0,odch=1)
{x=rnorm(n,mean=sr, sd=odch)
  sr_emp=mean(x)
  odch_emp=sd(x)
  return(list(x,sr_emp, odch_emp))
  #list(x,sr_emp, odch_emp) też powinno działać
}

Zadanie: sprawdzić działanie powyższej funkcji.

3.5 Funkcja jako wynik

Wynikiem działania funkcji może być inna funkcja:

potega=function(wykladnik)
{
  function(x) x^wykladnik
}
kwadrat=potega(2)
kwadrat(5)
## [1] 25
szescian=potega(3)
szescian(11)
## [1] 1331
pierwiastek=potega(1/2)
pierwiastek(2)
## [1] 1.414214

3.6 Funkcja jako argument

Funkcja może być też argumentem innej funkcji. Poniższa funkcja generuje próbę losową z rozkładu rozklad. Domyślnie przypisany jest rozkład normalny. Trzy kropki w argumencie funkcji służy do pisania “wszystkich pozostałych argumentów” i wykorzystywany jest do przekazywania przez funkcję swoich argumentów do innej funkcji w swoim ciele.

losuj10 = function(rozklad=rnorm, ...)
{
  rozklad(10,...)
}

losuj10()#standardowy rozkład normalny, domyślny dla funkcji
##  [1]  0.62593232 -1.47255952 -1.04345064 -0.02496408  0.03272361 -0.59413764
##  [7] -0.12172530 -0.71374416 -0.41672324 -2.21485226
losuj10(runif, -5,5)#... służą do zadania przedziału na którym określony jest rozkład jednostajny (standardowo jest to przedział [0,1])
##  [1]  2.635771 -3.889755  4.107393 -1.326578  3.753521 -4.879303 -4.371088
##  [8]  0.801958 -3.057841 -4.605183

Inny przykład funkcji i wywołania

wykres=function(funkcja=sin,a=0,b=10)
{
  x=seq(a,b,length.out=1001)#sprawdzić, za co odpowiada argument length.out
  y=funkcja(x)
  plot(x,y)
}
wykres() #wywołanie z domyślnymi argumentami

wykres(cos,2,3) #wywołanie z własnymi argumentami

f=function(x) -2*cos(x)+x^2 #"nowa funkcja matematyczna"
wykres(f,0,1)

3.7 Leniwe argumenty, wartościowanie leniwe w R

Wartościowanie leniwe (ang. lazy evaluation, ewaluacja leniwa) – strategia wyznaczania wartości argumentów funkcji tylko wtedy, kiedy są potrzebne (na żądanie).

Zaletami tego podejścia są możliwość obliczenia wartości funkcji nawet wtedy, gdy nie jest możliwe wyznaczenie wartości któregoś z jej argumentów, o ile tylko nie jest on używany, wzrost wydajności dzięki uniknięciu wykonywania niepotrzebnych obliczeń oraz możliwość tworzenia nieskończonych struktur danych. Wadą wartościowania leniwego jest to, że mogą nie wystąpić (być może oczekiwane) skutki uboczne procesu wyznaczania wartości argumentów.

Przeciwieństwem wartościowania leniwego jest wartościowanie zachłanne, stosowane w większości popularnych języków programowania.

(przekopiowane z Wikipedii)

Przykład:

leniwiec=function(x=y)
{
  y=2
  cat(x) #polecenie służące wypisaniu "x" w konsoli
}
y=1
leniwiec(5) #działa jak można by się spodziewać
## 5
leniwiec() #domyślny argument może sprawić problem...
## 2

Jaka jest różnica?

W przypadku pierwszego wywołania leniwiec(5) funkcja ma wypisać w konsoli x. I teraz dopiero funkcja zastanawia się, co to jest ten “x”? Domyślnie to byłby jakiś “y”, ale wywołanie funkcji mówi, że “x” ma być równe 5! Zatem funkcja wypisze liczbę 5.

W drugim przypadku funkcja leniwiec() ma to samo zadanie (wypisanie “x”a), ale nie ma zadanego argumentu w wywołaniu, ale ma argument domyślny. Mam wypisać “x”. Ale co to jest ten “x”?. Domyślnie “x=y”. Ale co to jest ten “y”? Są dwa “igreki”. Jeden globalny, ten y=1, i ten lokalny y=2. Funkcja leniwa wypisze “x=y” dla tego lokalnego y=2. Funkcja nie “zastanawia się”, tzn. nie przypisuje wartości do zmiennych w momencie wywołania funkcji, a dopiero, gdy w ciele funkcji wartość jest jej potrzebna.

3.8 Zadania - funkcje

3.8.1 Zadanie

Napisz funkcję funkcja_kwadratow(), która jako argumenty przyjmuje zmienne a, b, c, które będą odpowiadać współczynnikami równania kwadratowego. Następnie zwrócić w postaci listy, której nazwy elementów to “miejsce_zerowe” i “ekstremum” odpowiednio miejsca zerowe funkcji oraz ekstremum funkcji. Przyjmij jakieś wartości domyśle na argumentów.

3.8.2 Zadanie

Napisz funkcję BMI(), która będzie pobierać wagę i wzrost jako argumenty. Funkcja powinna obliczyć Indeks Masy Ciała (BMI), a następnie sklasyfikować wynik od wygłodzenia do otyłości (szczegóły znajdziesz na stronie: BMI wikipedia).

Jako wynik funkcja powinna zwracać zestaw 4 elementów: masę, wzrost, obliczony BMI, klasyfikację.

Przetestuj swoją funkcję dla trzech różnych zestawów danych.

3.8.3 Zadanie

Rok przestępny: jeżeli rok A nie jest podzielny przez 4, to A nie jest rokiem przestępnym. Jeżeli A jest podzielne przez 4, to A jest rokiem przestępnym, chyba że A jest podzielne przez 100, ale nie przez 400. Przykłady:
- rok 1901 nie jest rokiem przestępnym, bo nie jest podzielny przez 4
- rok 2004 jest rokiem przestępnym, ponieważ jest podzielny przez 4, a nie przez 100
- rok 2100 nie jest rokiem przestępnym, ponieważ dzieli się przez 4, przez 100, ale nie przez 400
- rok 2000 jest rokiem przestępnym, bo jest podzielny przez 4, przez 100 i przez 400.

  1. Napisz funkcję przestepny=funkcja(A), przytrzymując w argumencie rok A, która określa, czy rok A jest rokiem przestępnym, czy nie. Możesz użyć np. polecenia A%%4 służącego do obliczania reszty z dzielenia liczby A przez 4.

  2. Przetestować program na powyższych przykładach.

Uwaga: program powinien wypisać odpowiedź pełnym zdaniem, np. “Rok A jest/nie jest rokiem przestępnym”. Można wykorzystać polecenie paste.

4 Wybrane funkcje matematyczne

Przedstawimy klika funkcji matematycznych, które można znaleźć w programie R.

4.1 Operacje na zbiorach

union(x,y) Suma wektorów x i y
intersect(x,y) Część wspólna wektorów x i y
seldiff(x,y) Różnica wektorów x minus y
setequal(x,y) Wartość logiczna TRUE lub FALSE w zależności czy zawartości wektorów są sobie równe
is.element(el,set) Wartość logiczna TRUE lub FALSE w zależności, czy element el należy do wektora set

4.2 Wielomiany

Funkcje do tworzenia i operowania na wielomianach są zebrane w bibliotece polynom. Zatem, za pierwszym razem prawdopodobnie będzie wymagana instalacja biblioteki za pomocą komendy install.packages("polynom"). Za kolejnymi razem wystarczy załadować bibliotekę używając komendy library(polynom).

Zdefiniujmy dwa wielomiany za pomocą funkcji polynomial(coef=c(0,1)), gdzie w argumencie coef można podawać współczynniki wielomiany w porządku rosnącym.

library(polynom)
p1 <- polynomial(c(2,0,1))
p1
## 2 + x^2
p2 <- polynomial(c(2,2,1,1))

Na wielomianach możemy wykonywać między innymi poniższe operacje:

p1+p2 Dodawanie dwóch wielomianów
integral(p1, c(0,1)) Całkowanie wielomianów na przedziale (0,1)
deriv(p1) Różniczkowanie wielomianu
solve(p1) Wyznaczanie miejsc zerowych wielomianu

4.3 Ekstrema funkcji

Do numerycznego wyznaczenia ekstremów funkcji można użyć funkcji optimize(), która wyznacza ekstrema lub funkcji uniroot(), która wyznacza miejsca zerowe.

Warto podkreślić ze funkcja uniroot() zadziała tylko gdy pierwiastki funkcji są przeciwnych znaków, co jest dość dużym ograniczeniem. Sposób zastosowanie tych funkcji przedstawimy na poniższym przykładzie. Aby dowiedzieć się więcej o argumentach jakie funkcje optimize() i uniroot() mogą przyjmować zachęcamy do sprawdzenia w helpie.

Przykład:

f <- function(x){
  (x-7)^2-x
}
optimize(f, interval=c(-2,2)) #domyślnie wyznacza minimum
## $minimum
## [1] 1.99994
## 
## $objective
## [1] 23.00066
optimise(f,interval = c(-2,2), maximum = TRUE) # wyznaczenie maksimum
## $maximum
## [1] -1.99994
## 
## $objective
## [1] 82.99885
uniroot(f, interval = c(-1,10))
## $root
## [1] 4.807418
## 
## $f.root
## [1] -4.69523e-06
## 
## $iter
## [1] 8
## 
## $init.it
## [1] NA
## 
## $estim.prec
## [1] 6.103516e-05

4.4 Rachunek różniczkowo-całkowy

Do symbolicznego różniczkowania można użyć funkcji D() lub deriv(), które obliczają to samo, natomiast różnią się sposobem przekazywania argumentów. Spójrzmy na poniższe przykłady:

D(expression(3*(x^5)-(x-6)^(-1/2)),"x")
## 3 * (5 * x^4) - (x - 6)^((-1/2) - 1) * (-1/2)
deriv(~3*(x^5)-(x-6)^(-1/2),"x")
## expression({
##     .expr3 <- x - 6
##     .expr5 <- -1/2
##     .value <- 3 * x^5 - .expr3^.expr5
##     .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
##     .grad[, "x"] <- 3 * (5 * x^4) - .expr3^(.expr5 - 1) * .expr5
##     attr(.value, "gradient") <- .grad
##     .value
## })

Do całkowania numerycznego używamy funkcji integrate()

f <- function(x){
  sin(x)^2
}
integrate(f,0, 100)
## 50.21832 with absolute error < 2.4e-08