Czym jest pakiet
Pakiet to zestaw funkcji, dokumentacji, a czasem też danych, który rozszerza R. Bazowy R daje ci wektory, modele i wykresy, a pakiety dają całą resztę, i ta "cała reszta" jest ogromna. CRAN (Comprehensive R Archive Network) gromadzi około 20 000 pakietów, a każdy z nich przed publikacją przechodzi testy zgłoszeniowe CRAN. To repozytorium jest głównym powodem, dla którego R pozostaje konkurencyjny w pracy z danymi: jakakolwiek jest analiza, ktoś prawdopodobnie już ją spakował.
CRAN nie jest jedynym źródłem. Bioconductor gromadzi ekosystem bioinformatyczny, a wiele pakietów w fazie rozwoju żyje na GitHubie (można je zainstalować przez remotes::install_github()). Na początku możesz jednak traktować CRAN jako domyślne źródło, a pozostałe jako coś, co spotkasz, gdy README każe ich użyć.
Kilka pakietów przychodzi razem z samym R (stats, utils, graphics i pokrewne) i wczytuje się automatycznie, dlatego mean() i plot() po prostu działają. Wszystko inne wymaga opisanego niżej dwuetapowego rytuału.
install.packages() raz, library() w każdej sesji
To zamieszanie numer jeden wśród początkujących, więc tu jest tak jasno, jak się da. Uruchomienie pakietu to dwie różne czynności o dwóch różnych czasach życia:
install.packages("dplyr") # ONCE per machine: downloads from CRAN and installs
library(dplyr) # EVERY session: loads it so your code can use it
install.packages("dplyr")jest jak kupno książki: robisz to raz, a potem stoi na twojej półce (dysku). Zwróć uwagę na cudzysłowy: przekazujesz nazwę jako napis.library(dplyr)jest jak zdjęcie książki z półki: robisz to na początku każdej sesji R (w praktyce na początku każdego skryptu). Cudzysłowy nie są tu potrzebne, bolibrary()jest wyjątkowe i przyjmuje samą nazwę (library("dplyr")też działa, jeśli wolisz spójność).
Oba rodzaje błędów mówią, który krok pominięto. Error: there is no package called 'dplyr' z library() oznacza, że pakietu nigdy nie zainstalowano. Error: could not find function "filter" (albo "%>%") w połowie skryptu oznacza, że pakiet jest zainstalowany, ale ta sesja go nie wczytała. Umieszczenie wszystkich wywołań library() na samej górze skryptu, a nie rozrzuconych po nim, sprawia, że drugi błąd widać w pierwszej sekundzie, a przy okazji daje listę zależności skryptu. Instalacja tidyverse działa tak samo: install.packages("tidyverse") raz, library(tidyverse) w każdej sesji, co w jednej linii wczytuje dplyr, ggplot2 i resztę podstawowego zestawu.
Czego nie należy robić, to zostawiać install.packages() w skrypcie, który uruchamiasz wielokrotnie albo udostępniasz innym: pobiera pakiet przy każdym uruchomieniu i może zaskoczyć tego, kto skrypt wykonuje. Instalacja to czynność w konsoli, wczytywanie to czynność w skrypcie.
require() i pkg::fun()
require() wygląda jak synonim library() i często tak jest nadużywane. Różnica polega na tym, co się dzieje, gdy pakietu brakuje: library() zatrzymuje się z błędem, a require() wypisuje ostrzeżenie, zwraca FALSE i pozwala skryptowi działać dalej. Zwykle kończy się to dwadzieścia linii później mylącym "could not find function" zamiast uczciwego komunikatu "no package called". Do wczytywania zależności używaj library(): głośny błąd na samym początku to zaleta. require() przydaje się tylko w warunkach, w których liczy się właśnie jego wartość zwracana:
if (!require(praise)) {
install.packages("praise")
library(praise)
}
Jest też sposób na użycie pakietu bez wczytywania go: operator :: wywołuje jedną funkcję po jej pełnym adresie, package::function(). Pakiet musi być zainstalowany, ale nic nie zostaje dołączone do twojej sesji:
(stats i tak wczytuje się automatycznie, więc zwykłe sd() też działa, ale składnia jest taka sama dla każdego zainstalowanego pakietu.) :: sprawdza się w dwóch miejscach: przy jednorazowych wywołaniach, gdy pełna linia library() to przesada, oraz przy rozstrzyganiu niejednoznaczności, gdy dwa wczytane pakiety eksportują tę samą nazwę. dplyr::filter() kontra stats::filter() to klasyczna kolizja.
Aktualizowanie pakietów
Pakiety rozwijają się niezależnie od R, więc aktualizacja należy do ciebie:
update.packages() # offers to update everything outdated
update.packages(ask = FALSE) # same, without prompting per package
Jedna nieoczywista zasada: pakiety są budowane pod konkretną wersję major.minor R. Gdy aktualizujesz sam R (np. z 4.3 do 4.4, zobacz instalację R), twoja stara biblioteka pakietów zwykle nie jest przenoszona, a rozwiązaniem jest po prostu ponowna instalacja używanych pakietów w nowej wersji. To dziesięć minut z install.packages(), a nie katastrofa, ale zaskakuje każdego, gdy pierwszy raz jego skrypty witają świeżą instalację R ścianą błędów "no package called".
Co masz zainstalowane
Trzy funkcje odpowiadają na pytanie "co jest zainstalowane i gdzie":
installed.packages()[, "Version"] # every installed package with its version
sessionInfo() # R version + what THIS session has loaded
.libPaths() # the folders where packages are installed
installed.packages() zwraca macierz z jednym wierszem na pakiet; zwykle interesuje cię kolumna Version. sessionInfo() to narzędzie do odtwarzalności: wklej jego wynik do zgłoszenia błędu, a czytelnik pozna twoją wersję R, system operacyjny i dokładne wersje wszystkich wczytanych pakietów. .libPaths() pokazuje foldery bibliotek, które przeszukuje R. Świadomość, że istnieje, wyjaśnia zagadkę "gdzie właściwie trafił ten pakiet?" i to, dlaczego na wspólnych komputerach czasem liczą się uprawnienia administratora.
Pakiety, które warto znać
Nie potrzebujesz ich dzisiaj, ale będziesz je spotykać bez przerwy. Wiedza o tym, do czego służy każdy z nich, pomaga czytać cudzy kod:
- dplyr: czasowniki do przekształcania danych, czyli
filter,mutate,group_by,summarize. - ggplot2: standardowy pakiet do wykresów; większość grafik z R, które widzisz w sieci, to ggplot2.
- tidyr: przekształcanie danych między formą szeroką i długą (
pivot_longer,pivot_wider). - readr / readxl: odpowiednio szybkie wczytywanie CSV i wczytywanie plików Excela.
- lubridate: daty, które zachowują się tak, jak się spodziewasz.
- stringr: spójne operacje na napisach.
- data.table: alternatywny, wysokowydajny ekosystem ramek danych; inny dialekt niż tidyverse, uwielbiany przy dużych danych.
- shiny: interaktywne aplikacje webowe napisane w całości w R.
Pierwsze sześć to rdzeń tidyverse i przychodzą razem przez install.packages("tidyverse"). Nie ma obowiązku używania żadnego z nich (bazowy R potrafi to wszystko), ale to w tym ekosystemie żyje większość nowoczesnego kodu R.
Co warto zapamiętać
- CRAN gromadzi około 20 000 sprawdzonych pakietów; Bioconductor i GitHub obejmują resztę.
install.packages("name")raz na komputer (cudzysłowy wymagane);library(name)raz na sesję, na początku skryptu.library()zgłasza głośny błąd i to dobrze;require()zwracaFALSE, co przydaje się tylko w warunkach.pkg::fun()używa jednej funkcji bez dołączania pakietu i rozstrzyga kolizje nazw.update.packages()utrzymuje pakiety w aktualności; większa aktualizacja R oznacza ponowną instalację pakietów.sessionInfo()pozwala komuś (albo tobie w przyszłości) dokładnie powiedzieć, na czym działał twój kod.
Dalej: katalog roboczy, czyli miejsce, w którym R szuka plików, i powód, dla którego to pierwsza rzecz do sprawdzenia, gdy wczytywanie danych się nie udaje.
Najczęściej zadawane pytania
Jak zainstalować pakiet w R?
Uruchom install.packages("name") z nazwą pakietu w cudzysłowie, np. install.packages("dplyr"). R pobiera go z CRAN i instaluje na twoim komputerze. Robisz to tylko raz na danym komputerze, a potem wczytujesz go w każdej sesji przez library(dplyr).
Czym różni się install.packages() od library()?
install.packages("dplyr") pobiera pakiet na twój komputer, raz na komputer. library(dplyr) wczytuje już zainstalowany pakiet do bieżącej sesji, raz na sesję, zwykle na początku każdego skryptu. Instalacja bez wczytania nie daje niczego, czego można użyć; wczytanie bez instalacji kończy się błędem "there is no package called 'dplyr'".
Czym różni się library() od require() w R?
Obie funkcje wczytują pakiet, ale przy niepowodzeniu library() zatrzymuje się z błędem, a require() tylko ostrzega i zwraca FALSE. Dlatego library() pasuje do skryptów (głośny błąd od razu na początku), a require() przydaje się tylko w warunkach typu if (!require(pkg)) install.packages(pkg).