86 l>HMiilhry
Problem możo pojawić się, jeżeli chcemy skorzystać z operatorów arytmetyk nyi li, któic w formulach mają specjalne znaczeuie. Znak + w formule zostanie z'v terprotowany jako dodanie termu do formuły, a nie jak operację dodawania. Ąf tomu zaradzić, należy skorzystać z funkcji I() (identyczności). Argumenty tej I cjl traktowane będą jako wyrażenia arytmetyczne i tak:
# to jest formula opisująca zależność y od zmiennych a i b y ' a+b
# to jest formula opisująca zależność y od zmiennej suma a i b y " I(a+b)
# to jest bardziej skomplikowana formula o dwóch termach y ~ ICa+b) + I(a*(b-3))
Bardzo przydatnym termem jest"." (kropka), który oznacza zależność od wszy kich pozostałych kolumn danej ramki danych (w funkcji wykorzystującej tę formuł powinien być podany argument data, wskazujący ramkę danych). Przykłady form z tym termem umieszczone są poniżej.
. -1 ' -. + I(a+b)
Nazwy zmiennych pojawiających się w formule powinny być widoczne w aktu alnym środowisku lub też powinny wskazywać kolumny ramki danych, wskaż przez dodatkowy argument. Poniższe trzy przykłady dają identyczny wynik.
tt podajemy do formuły nazwy zmiennych y - rnorm(lOO) x « rnorm(lOO) lm(y"x)
U podajemy do formuły nazuty kolumn we wskazanej ramce danych dane = data.frajne(a°y, b=x) lm(a~b, data*dane)
# każemy wybrać wszystkie kolumny ze wskazanej ramki danych data=dane)
Przykłady wykorzystania formuł znajdują się w rozdziale 3.4 oraz w podrozd lach poświęconych wykresom graficznym.
You can be nmximally lazy, but still be efHeient. Kevin Mtirphy (dcscribing tho implement&tion of an algorithm) fortune(!2)
O mechanizmie leniwej ewaluacji (ang. lazy eualuation) pisaliśmy przy okazji fun cji suitchf). Dotyczy on nie tylko tej jednej funkcji ale wszystkich funkcji w R W przypadku każdej funkcji, argumenty podane w wywołaniu funkcji nie są wyzna czauo, póki ich wartość nie jest potrzebna. W większości niskopoziomowych języków programowania stosowana jest gorliwa ewaluacja, co oznacza, że argumenty funk i ji są wyznaczane przed jej uruchomieniem a do funkcji trafiają wyłącznie wyn nwuluacjl argumentów. W R jest inaczej.
Prześledźmy poniższy przykład użycia funkcji, która na pierwszy rzut oka jest
;< identycznością.
'j t Określmy funkcje której wynikiem jest pierwszy argument wieldentycznosc <- function(x) < żmiennaGlobalna «- 3 -+ x
inicjujemy zmienną globalną wartością 2 jimiennaGlobalna ■ 2 ^ p czy tego wyniku oczekiwaliśmy?
5^ .prawieldentycznosc (zmiennaGlobalna)
W przykładzie powyżej wywoływana jest funkcja z argumentem zmiennaGlobalna. Wartość tego argumentu nie jest wyznaczana, aż do ostatniej linii kodu funkcji, ponieważ nigdzie wcześniej zmienna x (argument) nie jest użyta. Dlatego wynikiem funkcji wywołanej z argumentem równym 2 jest wartość 3, pomimo że argument funkcji prawieldentycznoscO stał się trójką dopiero wewnątrz tej funkcji. Wynik byłby inny, gdybyśmy wcześniej wymusili wyznaczenie wartości argumentu.
> # w drugiej linii wartość zmiennej x jest wyznaczana, przez co zmiana
■ wartości zmiennaGlobalna w linii trzeciej nie wpływa na wynik funkcji ('> . prawieldentyeznosc <- function(x) {
* x ■> x + 0
I* ■ zmiennaGlobalna «- 3 -•+ x
;•>.. zmiennaGlobalna * 2
> prawieldentycznosc(zmiennaGlobalna)
Cl] 2
i- Tym razem wynikiem funkcji prawieldentycznoscO jest 2, zgodnie z oczekiwaniami, pomimo iż na pierwszy rzut oka instrukcja x = x + 0 nie powinna wpłynąć na wynik.
Nie dość, że argumenty funkcji nie są wyznaczane bez potrzeby, to jeszcze funkcja ma pełną informację o tym jakie wyrażenia zostały podane jako argumenty. Poniżej umieszczamy przykład, w którym wyrażenie będące argumentem funkcji odczytujemy o wypisujemy na ekranie.
> * w poniższej funkcji używając poleceń deparseO i substituteO j: wyświetlamy co zostało podane jako argument funkcji
> priatexpr <- function(expr){
ł cat(deparse(substitute(expr)))
> * funkcja wypisuje wyrażenie, które jest argumentem printexpr(3+2 - log(14))
3 + 2 - log(14)