Zmienne
Miałaś/eś już okazję trochę posługiwać się zmiennymi, przyszła dobra pora, żeby uporządkować, co już o nich wiemy.
Po pierwsze, co może być w nazwie zmiennej?
W nazwie mogą być litery, cyfry oraz znaki '_' i '.'. Teoretycznie mogą być polskie znaki, ale niekoniecznie w każdej wersji R-a, więc lepiej na wszelki wypadek nie używać, żeby się nie przyzwyczajać bez potrzeby. Mimo, że nazwa może zawierać cyfry i znaki musi się chociaż zacząć literą. Należy też pamiętać, że R rozróżnia duże i małe litery, tj. moja_zmienna to inna nazwa niż Moja_zmienna.
Po drugie, jak warto nazywać zmienne?
Wielu początkujących programistów uważa, że nazwy warto skracać, bo po co takie długie. (Wielu zaawansowanych niestety też.) Nazywają zmienne a, b, c, albo l_zad, sr_oc zamiast liczba_zadan czy srednia_ocen. Nie wiem, czy czas, jaki zaoszczędzili na pisaniu tych nazw jest rzeczywiście wart robienia tego, mam nadzieję, żę chociaż robią z nim coś wartościowego. Zmienne warto nazywać tak, żeby dokładnie wiedzieć, co się pod nimi kryje, i to nie tylko w tej chwili, ale też kiedy za miesiąc zajrzy się do swojego skryptu czy w historię komend. Kiedy wszystkie zmienne są ponazywane po ludzku program można normalnie przeczytać i zrozumieć, o co w nim chodzi; linijka "wydatki = srednia_pensja * liczba_pracownikow" jest zupełnie jasna, linijka "c = a * b" zupełnie nie. Oczywiście obie robią to samo (o ile na odpowiednich zmiennych są te same wartości), ale kiedy po pięciu minutach obliczeń wrócisz parę linijek do góry i będziesz próbował zrozumieć czemu jakiś wynik wychodzi Ci dziwny, ciężko będzie Ci zrozumieć co właściwie siedzi pod zmienną c i skąd się tam wzięło. Dużo łatwiej jest prześledzić własny tok rozumowania z jasno nazwanymi zmiennymi. Jest pewna bardzo cenna zasada: program powinno pisać się w pierwszej kolejności po to, żeby mogło się go wygodnie przeczytać, dopiero w drugiej kolejności żeby działał.
Po trzecie, jak się tworzy zmienną?
To już pojawiało się w poprzednich rozdziałach, ale przypomnę: piszemy nazwę zmiennej, pojedynczy znak równości, a potem wartość, którą chcemy przypisać na zmienną. Wartość nie musi być podana wprost, może to być jakieś skomplikowane wyrażenie, które R dopiero musi obliczyć. W tym miejscu wypada wspomnieć również o drugim sposobie zapisywania wartości na zmienną: za pomocą operatora "<-", oczywiście bez spacji pomiędzy < a -:
> a = 10 > a [1] 10 > a <- 4 * 2 > a [1] 8 > a < - "to chyba nie wyjdzie" Error in -"to chyba nie wyjdzie" : invalid argument to unary operator
Te dwa sposoby przypisania różnią się nieznacznie, ale nie jest to specjalnie istotne. Osobiście używam "=", głównie przez przyzwyczajenie z innych języków programowania. Operator "<-" ma tę ciekawą własność, że można go też zapisać w drugą stronę:
> 3 -> a > a [1] 3
I jeszcze jedna pożyteczna rzecz przy tworzeniu zmiennych: jeżeli zapisujemy coś na zmienną, a jednocześnie chcemy, żeby R nam wypisał to na ekran, owo przypisanie możemy wziąć w okrągłe nawiasy:
> ( a = 128 + pi ) [1] 131.1416
Po czwarte, co może być zapisane na zmienną?
Właściwie wszystko. Może to być liczba, TRUE / FALSE (wartość logiczna), wektor, macierz, funkcja, napis...
> zmienna_z_liczba = 4 > jakis_napis = "ala ma kota" > wektor = c( zmienna_z_liczba, 6, jakis_napis) > ( zmienna_z_wartoscia_logiczna = 3 > 2 ) [1] TRUE > zmienna_z_funkcja = sqrt > zmienna_z_funkcja(9) [1] 3 > zmienna_z_funkcja(zmienna_z_liczba) [1] 2 > zmienna_z_funkcja(jakis_napis) Error in zmienna_z_funkcja(jakis_napis) : non-numeric argument to mathematical function
...chciałam tylko sprawdzić, czy dalej umiem zdenerwować R-a. No tak, kazałam mu wykonać funkcję, zapisaną pod zmienną zmienna_z_funkcja, na czymś, co jest zapisane na zmiennej jakis_napis: pod zmienna_z_funkcja kryje się funkcja sqrt, czyli pierwiastek, a pod jakis_napis - napis "ala ma kota". Napisów pierwiastkować się nie da, i w ogóle żadnych "mathematical function" na nich wykonywać, bo są "non-numeric", o czym R mnie uprzejmie informuje.
Po piąte, czy zmienne mogą się zmieniać?
Oczywiście! Po to nazywają się zmienne. Jeśli programowałaś/eś kiedyś w innych językach być może spotkałaś/eś się z tym, że wprawdzie mogą się zmieniać, ale nie mogą zmieniać typów, tj. jeśli raz powiedziałam, że jakis_napis to zmienna trzymająca napis, to nie mogę teraz kazać mu zapisać na nią liczby. No więc w R-ze tak nie jest. Zmienne mogą się zmieniać jak im się żywnie podoba.
> a = 12 > a [1] 12 > a = 15 > a [1] 15 >( a = a + 3 ) [1] 18 > a = "a teraz to napis, paczcie" > a [1] "a teraz to napis, paczcie"
Coś godnego uwagi dzieje się w poleceniu "a = a + 3": zmieniamy wartość zmiennej a, a jednocześnie używamy tej zmiennej do wyliczenia nowej wartości. Czy to się R-owi nie pomiesza? Skądże - R najpierw obliczy sobie to, co jest z prawej strony, czyli weźmie zmienną a (wtedy wynoszącą 15), doda do niej 3, wyjdzie mu 18, i wtedy ten wynik podstawi pod zmienną a.
Warto wspomnieć, że jeśli na zmienną zapisujemy inną zmienną, R tak naprawdę zapisuje wartość. Na przykład w tym fragmencie kodu:
> a = 10 > b = a
R nie zapamiętuje, że b zawsze ma być równe tyle, co a. Kiedy przypisujemy jakąś wartość na zmienną, R wylicza, co to za wartość (kiedy piszemy a=10 wiele do liczenia nie ma, po prostu wychodzi mu 10) i zapamiętuje ją pod nazwą zmiennej. Jeśli za chwilę każemy mu zapamiętać, że b jest jednak równe 14, zmieni tylko wartość b, a pozostanie nieruszone. Podobnie odwrotnie - jeśli każemy mu teraz zapamiętać, że a jest równe 42, R nie pomyśli "acha, to teraz a to 42, a ponieważ b było warte a, to b teraz też musi być 42". b pozostanie jakie było.
> a [1] 10 > b [1] 10 > b = 14 > b [1] 14 > a [1] 10 > b = a > a [1] 10 > b [1] 10 > a = 42 > a [1] 42 > b [1] 10
Po szóste, co zrobić, jeśli zapomniałam/em, jak nazwałam/em moją zmienną?
Jeżeli pamiętasz chociaż jak zaczyna się jej nazwa, możesz zacząć ją pisać i nacisnąć tabulator; jeśli R zna w tej chwili tylko jedną rzecz, której nazwa się tak zaczyna po prostu uzupełni Ci linię nazwą Twojej zmiennej; jeśli zna kilka, uzupełni tylko tyle, ile jest pewien, a kiedy naciśniesz tabulator jeszcze raz podpowie wszystkie nazwy, które możesz wpisać. Możesz również użyć funkcji "ls()" - po wpisaniu "ls()" R wyświetli wektor z wszystkimi stworzonymi przez Ciebie obiektami. Jeśeli pracujesz w RStudio, możesz też zajrzeć do okna z prawym górnym rogu, gdzie znajdziesz spis wszystkich używanych obecnie zmiennych.
Po siódme, na co jeszcze warto zwracać uwagę nazywając zmienną?
Na to, czy zmienna lub funkcja o takiej nazwie już nie istnieje. I nie chodzi tu tylko o zmienne stworzone przez Ciebie. Przykładowo, w rozdziale o kalkulatorze używaliśmy zmiennej pi - nie musieliśmy wcześniej mówić R-owi, ile ona jest warta, R sam z siebie zna zmienną pi. Jeżeli naszą zmienną nazwiemy pi, stracimy to, co wcześniej było na pi zapisane.
Co ciekawe, nic wielkiego się nie stanie jeśli nazwiemy zmienną nazwą jakiejś funkcji - kiedy będziemy z niej korzystać jak ze zmiennej, R będzie brał jej wartość jako zmiennej, kiedy jak z funkcji - będzie używał funkcji.
> sum # tu jeszcze sum jest funkcja sumujaca elementy wektora function (..., na.rm = FALSE) .Primitive("sum") > sum + 1 # nie mozna dodawac funkcji i liczby, bedzie error Error in sum + 1 : non-numeric argument to binary operator > sum( c(1,2,3) ) # uzywamy sum jako funkcji [1] 6 > sum = sum( c(1,2,3) ) # a teraz zapisujemy na zmienna sum to co nam wyszlo > sum # sum to teraz przede wszystkim zmienna i R wypisze jej wartosc [1] 6 > sum + 1 # do zmiennej juz mozna dodawac [1] 7 > sum( c(12,13) ) # ...ale caly czas mozemy tez uzywac sum jako funkcji! [1] 25
Mimo wszystko nie polecam tego robić. Czasem zdarza się, że chcemy na zmienną zapisać jakąś funkcję. Na przykład mamy kawałek kodu, który wielokrotnie coś robi z liczbami, i do tej pory to coś polegało na dodawaniu ich, ale spodziewamy się, że może któregoś dnia zdecydujemy, że chcielibyśmy wyliczać z nich średnią. Zamiast podmieniać we wszystkich miejscach "sum" na "mean", możemy zrobić na samym początku tak:
Jeśli teraz stwierdzamy, że jednak chcemy liczyć średnią, a nie sumować, podmieniamy tylko na górze skryptu pierwszą linię na:
> co_robimy_z_liczbami = mean
Wszystkie pozostałe linie zostają takie same, i nagle zamiast sumować zaczynają liczyć średnią. Ale jeśli wcześniej nazwiemy jakąś zmienną sum, to nie zadziała :(
R zapisał sobie, że sum to 4. Wciąż można używać sum jako zwykłej funkcji, bo R swoje własne funkcje pamięta trochę gdzie indziej niż nasze własne zmienne i funkcje. Potem zapisał, że co_robimy_z_liczbami ma być równe sum, czyli 4 (najpierw sięgnął do naszych nazw zmiennych, żeby sprawdzić co to jest sum, nie do swoich funkcji). A potem każemy mu użyć co_robimy_z_liczbami jako funkcji, ale R nie rozumie o co nam chodzi, przecież nie ma takiej funkcji, co_robimy_z_liczbami to tylko nudna zmienna z liczbą.
Jeśli nazywamy zmienne polskimi nazwami jest raczej nieduża szansa, że cokolwiek w R-ze się tak nazywa, ale jeśli używamy nazw angielskich i/lub mocno skróconych takie ryzyko się pojawia. Jeśli mamy wątpliwości czy jakaś funkcja / zmienna już istnieje zawsze warto napisać ją i nacisnąć dwukrotnie tabulator - jeśli będzie wśród podpowiedzi to znaczy, że jest zajęta.
Po ósme, czy R zapamięta moje zmienne na zawsze?
Nie. Jeżeli zrobiłeś/aś zmienną liczba_kosiarek o wartości 23, a potem wyszedłeś/aś z R-a, R powinien zapytać Cię, czy chcesz zachować obszar roboczy (workspace): jeśli odpowiesz y (w terminalu) lub save (w RStudio), w katalogu, w którym R pracował stworzone zostaną ukryte pliki, w których zapisane będą wszystkie komendy, które wykonywałaś/eś, oraz wszystkie zmienne, które stworzyłeś/aś. Przy kolejnym uruchomieniu R-a wszystko to się załaduje i dalej będziesz miał(a) swoją zmienną liczba_kosiarek. Ale jeśli odpowiesz "n" lub "don't save", R oczywiście niczego nie zapisze i przy kolejnym uruchomieniu będzie znał tylko te nazwy, które ma zapisane na stałe, tj. swoje własne zmienne i funkcje.
Uwaga. Pliki z historią i danymi są zapisane w katalogu, w którym R akurat pracuje. Jeśli uruchamiasz R-a w terminalu, jest to po prostu katalog, w którym byłaś/eś, zanim wpisałaś/eś polecenie R. Jeśli uruchamiasz skrypt, będzie to katalog, w którym ów skrypt się znajduje. Zawsze możesz sprawdzić, gdzie R akurat pracuje, wpisując polecenie getwd() (jak get working directory). Jeśi nawet zapisałeś/aś obszar roboczy, ale następnym razem uruchomisz R-a z innego katalogu R nie znajdzie w nim żadnej historii i danych i uruchomi się nie załadowując niczego. Oczywiście to nie znaczy, że Twoje dane przepadły, po prostu musisz uruchomić R-a tak, żeby pracował w katalogu, gdzie są Twoje dane. Możesz też załadować dane i historię komend przy pomocy funkcji load() i loadhistory(), podając w nawiasach ścieżkę do plików z danymi.
> a # nie ma takiego obiektu, bedzie blad Error: object 'a' not found > load("/home/maciosz/katalog_w_ktorym_pracowal_R/.RData") > a # teraz juz jest, bo poprzednio go stworzylam, tylko zapisalo sie to w innym katalogu [1] 10
Jeżeli jakaś zmienna Cię denerwuje, bo zdefiniowałaś/eś ją przez pomyłkę, możesz ją usunąć z pamięci R-a poleceniem rm():
> wzorst = 1.53 # ups, literowka, niefajnie > wzorst [1] 1.53 > rm(wzorst) > wzorst Error: object 'wzorst' not found > imie = "florek" > oczy = "niebieskie" > waga = 66 > wzrost = 154 > ls() [1] "imie" "oczy" "waga" "wzrost" > rm(imie, oczy) > ls() [1] "waga" "wzrost" > rm( list = ls() ) > ls() character(0)
rm spodziewa się, że dostanie po prostu wypisane nazwy, jeśli są zapakowane w jakąś listę lub wektor (jak to jest w przypadku nazw zwróconych przez funkcję ls()), trzeba mu powiedzieć, że to lista, stąd owo "list = ls()" kiedy chcemy usunąć wszystko. Zauważmy, że przed character(0) nie ma napisu [1], co ma dużo sensu - character(0) to pusty wektor, a nie pierwszy element jakiegoś wektora.
Po dziewiąte, czy dużo jeszcze rzeczy muszę wiedzieć o zmiennych, żeby programować w R-ze?
Nie, to właściwie wszystko :) Zapraszamy do kolejnego rozdziału!