Kalkulator

Jak wspomniałam we wstępie, R służy wielu użytkownikom do rozmaitych obliczeń. Zacznijmy więc przygodę z R-em od zobaczenia, jak można policzyć różne proste rzeczy w R-ze.

Uruchom R-a (RGui, RStudio lub w terminalu) i wpisz jakieś proste działanie, np.:

> 40+2

Kiedy naciśniesz enter, R sprawdzi co napisałaś/eś, zrobi to, co od niego chcesz - w tym wypadku wykona dodawanie - i napisze, ile mu wyszło. O ile nie żyjesz w alternatywnej rzeczywistości, w której matematyka rządzi się innymi prawami niż u mnie, w linijce poniżej powinno się pokazać

[1] 42

Jeśli martwi Cię owo [1], przypominam, że w pewnym sensie R wszystko traktuje jako wektory - dla nas 42 to po prostu liczba, dla R-a wektor z jednym elementem 42. R po prostu informuje nas ową jedynką, że to pierwszy element wektora.

Zawsze kiedy poznaje się nowy język programowania dobrym pomysłem jest przetestować jego cierpliwość i spróbować go "zepsuć". Daje nam to po pierwsze dobre pojęcie o tym, co jest dla programu zrozumiałe a czego już nie zdzierża, a po drugie oswaja z komunikatami błędu - prędzej czy później na pewno pomylimy się pisząc jakąś komendę i R poinformuje nas grzecznie acz stanowczo, że nie umie zrobić tego, czego od niego chcemy; dobrze jest wtedy nie wpadać w panikę i spokojnie przeczytać komunikat, który nam wyświetli. Sprawdźmy na przykład, czy R dalej będzie wiedział o co nam chodzi, kiedy powciskamy dodatkowe spacje w nasze odawanie:

> 40 + 2
[1] 42
>   40   +     2
[1] 42
> 4 0 +2
Error: unexpected numeric constant in "4 0"

Ups. Wszystko szło dobrze, póki spacje wciskaliśmy dookoła liczb i operatora "+", ale nie spodobało się R-owi, kiedy rozdzieliliśmy spacją cyfry 4 i 0. Jeśli podobnie jak ja masz angielskojęzyczną wersję R-a komunikat brzmi tak jak powyżej, jeśli polskojęzyczną: BŁĄD: nieoczekiwano: stała liczbowa in "4 0" (albo coś w tym rodzaju, być może w nowszej wersji tłumaczenie jest zgrabniejsze). Wyjaśnienie błędu jest proste: R czyta sobie liczbę 4 i spodziewa się, że coś z nią chciemy zrobić, na przykład że dalej będzie znak +, -, * czy /, wtem! jakaś nowa liczba 0 (czy też "stała liczbowa", jak to ujął R), z którą nie wiadomo co trzeba zrobić; o co chodzi w takiej linijce? R nie rozumie, nie próbuje nawet czytać dalej, bo i po co, i od razu pisze błąd. Czyli spacje mogą oddzielać poszczególne składniki polecenia, ale jeśli coś jest samodzielnym składnikiem, to spacji do niego wciskać nie można, bo zmienia to jego znaczenie (możesz spróbować np. powciskać spacje do polecenia "print" i zobaczyć, cz R zrozumie o co chodzi).

Oczywiście dodawanie to nie wszystko co można robić:

> 21*2
[1] 42
> 50.75 - 2.34 - 6.41
[1] 42
> 84 / 2
[1] 42
> 35 * 1.2
[1] 42

...i oczywiście 42 to nie jedyny wynik, który można uzyskać.

Możemy jeszcze potęgować (operator ^ lub **), pierwiastkować (funkcja sqrt()), wyliczać resztę z dzielenia, czyli tzw. dzielenie modulo (%%):

> 2^10
[1] 1024
> 10 ** 2
[1] 100
> sqrt(100)
[1] 10
> 1000 ** 100
[1] 1e+300
> 5 %% 2
[1] 1
> 5 %% 3
[1] 2
> 5 %% 5
[1] 0

Zauważmy, jak R radzi sobie z dużymi liczbami: zamiast piasć pierdyliard zer, używa notacji wykładniczej, pisząc 1e+300, co oznacza: 1 * 10 ^ 300. Podobnie będzie robił z małymi liczbami:

> 4.2 / 1000000000
[1] 4.2e-09

Zamiast napisać 0.0000000042, pisze 4.2 * 10^-9, co wygodniej się czyta. Zwróć uwagę, że liczby z przecinkiem nie są tak naprawdę liczbami z przecinkiem, tylko z kropką.

Można liczyć nawet sinusy czy cosinusy:

> sin(pi/2)
[1] 1
> sin( pi / 3 )
[1] 0.8660254
> cos(0)
[1] 1
> sin(pi)
[1] 1.224647e-16

Zaraz, coś bez sensu, przecież sinus z pi to zero, o co ci chodzi R-ze? Mamy tu do czynienia ze swego rodzaju błędami obliczeniowymi - przy obliczeniach na bardzo małych liczbach może się zdarzyć, że program pomyli nam się o jedną biliardową w te czy we wte. Zauważmy, że to co dostaliśmy, jest tak naprawdę bardzo bliskie zeru: przecież to 1.2 * 10^-16, to prawie zero.

W R-ze obowiązuje kolejność działań jak wszędzie, którą jak wszędzie można zmienić dodając nawiasy (ale tylko okrągłe).

> 1 + 2 * 3
[1] 7
> (1 + 2) * 3
[1] 9
> 3 ** 5 %% 2
[1] 1
> (3 ** 5) %% 2
[1] 1
> 3 ** (5 %% 2)
[1] 3
> 5 %% 4 ** 2
[1] 5
> (5 %% 4) ** 2
[1] 1
> 4 * ( ( 12 + 423 / 54 ) - 0.54)
[1] 77.17333

Możemy też zrobić najnudniejsze działanie ever, czyli żadne działanie:

> 42
[1] 42

R czyta liczbę 42, robi z nią wszystko, co od niego chcemy, czyli nic, i pisze co mu wyszło. Przypomnienie z poprzedniego rozdziału: interpreter R-a wypisuje nam od razu wynik polecenia, które mu daliśmy; gdybyśmy umieścili w skrypcie linijkę "2 + 2" albo "42" R wykonałby wprawdzie działanie, ale nic by nie wydrukował, bo nikt go nie prosi. W skrypcie należy zapisać "print(2+2)".

Powiedzmy, że chcemy zrobić długą serię obliczeń na kilku szczególnie upierdliwych liczbach, których nie chce nam się za każdym razem wpisywać, bo łatwo o literówkę. Na przykład, zrobiliśmy zakupy i chcemy podliczyć różne statystyki - ile wydaliśmy na owoce, jaki to był procent całej kwoty, ile powinien każdy zapłacić, jeśli zakupy robiliśmy w 10 osób etc. Za każdym razem wpisywać ceny to bez sensu, w końcu się pomylimy. Ale nic prostszego! Nazwiemy sobie te liczby nazwami, które łatwo zapamiętać, i kiedy tylko będziemy chcieli ich użyć, po prostu wpiszemy nazwę, zamiast całej liczby. Na przykład:

> cena_ogorkow = 1.23
> waga_ogorkow = 0.64
> cena_bananow = 5.23
> waga_bananow = 1.02
> cena_czekolady = 4.57
> liczba_czekolad = 1
> cena_ogorkow * waga_ogorkow
[1] 0.7872

Informujemy R-a, że pod nazwą cena_ogorkow będzie się kryła liczba 1.23. Od teraz za każdym razem, kiedy napiszemy cena_ogorkow R będzie wiedział, że chodzi nam o liczbę 1.23. Mówimy, że cena_ogorkow to zmienna. Nic nie stoi na przeszkodzie, żeby na zmienne zapisywać wyniki obliczeń:

> koszt_owocow = cena_bananow * waga_bananow

Jeśli ciekawi nas, co kryje się pod jakąś zmienną, wpisujemy po prostu jej nazwę:

> koszt_owocow
[1] 5.3346

Działa to tak samo, jak wpisanie np. liczby 42, jak było pokazane wyżej.

Mniej więcej tutaj zawołałaś/eś może: "hola hola, wpisywanie cena_ogorkow jest jeszcze nudniejsze i bardziej literówkogenne niż wpisywanie 1.23! Rozumiem, że może to mieć sens dla dłuższych liczb, ale może proste warto wpisywać ot tak? Albo chociaż nazwać moją zmienną x zamiast cena_ogorkow?" No więc - nie. Dlaczego zmienne warto nazywać długimi nazwami opiszę dokładniej w rozdziale zmienne. Tymczasem powiem tylko, że R wie, że pisanie długich nazw może być upierdliwe, i może Ci podpowiedzieć, jaką nazwę zmiennej chcesz wpisać: wystarczy, że wpiszesz początek, np. "liczb" i naciśniesz tabulator a R sam uzupełni nazwę. Jeśli jest kilka zmiennych zaczynających się tak samo (np. kiedy wpiszesz "cena"), R po pierwszym wciśnięciu podpowie tylko tyle, ile jest pewien ("cena_"), a przy drugim wyświetli Ci podpowiedzi zmiennych, które zaczynają się od "cena_" - potem wystarczy, że napiszesz "o", naciśniesz tab i R sam uzupełni do "cena_ogorkow". Oprocz nazw zmiennych R podpowiada również nazwy funkcji i w ogóle wszystkiego, co możesz wpisać a co zaczyna się daną frazą. Jeśli chcesz sobie przypomnieć nazwy wszystkich zmiennych, które już stworzyłaś/eś, wpisz "ls()" - R wydrukuje wszystkie nazwy:

> ls()
[1] "cena_bananow"    "cena_czekolady"  "cena_ogorkow"    "koszt_calkowity"
[5] "koszt_owocow"    "liczba_czekolad" "waga_bananow"    "waga_ogorkow"

Przy okazji, zauważmy, pojawiło się [5] - bo koszt_owocow to piąty element wektora nazw.

Możemy jeszcze trochę zaszaleć:

> cena_ogorkow * waga_ogorkow + cena_bananow * waga_bananow + cena_czekolady * liczba_czekolad
[1] 10.6918
> koszt_calkowity = cena_ogorkow * waga_ogorkow + cena_bananow * waga_bananow + cena_czekolady * liczba_czekolad
> koszt_calkowity
[1] 10.6918
> koszt_calkowity / 10
[1] 1.06918
> koszt_owocow / koszt_calkowity
[1] 0.4989431

I znowu zachęcam żeby potestować jakie nazwy zmiennych są akceptowalne i spróbować zdenerwować R-a:

> nazwaZmiennej = 10
> a_moze_z_liczbami123 = 666
> a.teraz.z.kropkami = 1234
> sprobojmy+z+plusami = 100
Error in sprobojmy + z + plusami = 100 : object 'sprobojmy' not found
> zWykrzyknikiem! = 23
Error: unexpected '!' in "zWykrzyknikiem!"
> ze spacjami = 0
Error: unexpected symbol in "ze spacjami"
> 22 = 11
Error in 22 = 11 : invalid (do_set) left-hand side to assignment

R zrozumiał trzy pierwsze polecenia, dalej już zupełnie mu namieszaliśmy: najpierw myślał, że chcemy dodać obiekt (zmienną) sprobojmy do z, ale nie ma takiego obiektu, stąd error. Podobnie z wykrzyknikiem - tak jak +, ! ma znaczenie dla R-a, o którym zaraz. Ze spacjami nie zrozumiał, myślał, że piszemy o jakiejś zmiennej "ze", chcemy ją pewnie utworzyć czy coś, a dalej zamiast coś robić piszemy kolejną nazwę której nie zna. No i wreszcie - liczby jako nazwa zmiennej? To już zupełnie bez sensu.

Co jeszcze można by robić z liczbami? Na przykład porównywać je:

> 42 > 0
[1] TRUE
> 28 <= 13
[1] FALSE
> cena_ogorkow > cena_bananow
[1] FALSE
> waga_ogorkow == waga_bananow
[1] FALSE

R tym razem jako wynik podaje nie liczbę, ale TRUE lub FALSE. Zauważ, że kiedy pytamy, czy dwie wartości są równe, piszemy dwa znaki równości - jeden był wykorzystywany przy zapisywaniu na zmienną jakiejś wartości.

Na zakończenie obiecane "zaraz", kiedy wyjaśnię, jakie znaczenie dla R-a ma wykrzyknik. Otóż "!" to zaprzeczenie. Kiedy jakieś wyrażenie jako wynik nie daje liczby, ale TRUE / FALSE (wartość logiczną) możemy zaprzeczyć całe to wyrażenie i sprawić, że będzie odwrotne. "!" jest też wykorzystywany w operatorze "!=", czyli "różny od".

> ! 2 < 0
[1] TRUE
> 4 != 4.0
[1] FALSE
> 2 + 7 != 3 ** 2
[1] FALSE

Nie ma czegoś takiego jak "!<" czy "!>=", bo nie mają większego sensu, zamiast "!<" można napisać ">=" etc.

I to tyle jeśli chodzi o korzystanie z R-a jako kalkulatora :)  Dysponując tą wiedzą na pewno poradzisz już sobie z zadaniem Wyrażenia arytmetyczne. A za chwilę zanurzymy się jeszcze głębiej w odmęty R-a, poznając bodaj najczęściej używane struktury danych, jakimi są wektory i macierze.