Menu

Katalog roboczy w R: setwd(), getwd() i czyszczenie przestrzeni roboczej

Gdzie R szuka plików i jak nad tym panować: getwd(), setwd(), list.files(), czyszczenie środowiska przez rm(list = ls()) i dlaczego automatyczny zapis .RData to pułapka.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Czym jest katalog roboczy

Każda sesja R działa „w” dokładnie jednym folderze: katalogu roboczym. Za każdym razem, gdy używasz ścieżki względnej, czyli takiej, która nie zaczyna się od korzenia systemu plików, R rozwiązuje ją względem tego folderu. read.csv("data.csv") nie znaczy „znajdź data.csv gdzieś na moim komputerze”; znaczy „otwórz plik o nazwie data.csv w katalogu roboczym”.

Ten jeden fakt wyjaśnia najczęstszy błąd początkujących w R:

read.csv("data.csv")
# Error in file(file, "rt") : cannot open the connection
# In addition: Warning message: cannot open file 'data.csv': No such file or directory

Plik istnieje, tylko nie w folderze, w którym R właśnie szuka. Z twoim wywołaniem read.csv wszystko jest w porządku; po prostu katalog roboczy sesji i lokalizacja pliku się nie zgadzają. Dwie funkcje poniżej zamieniają tę zagadkę w dziesięciosekundową diagnozę.

getwd() i setwd()

getwd() (get working directory) mówi, gdzie R szuka w tej chwili:

Uruchom to, a zobaczysz ścieżkę bezwzględną, czyli folder, do którego przypięta jest ta sesja. setwd() (set working directory) go zmienia:

setwd("C:/Users/rosa/projects/sales-analysis")   # Windows: use / not \
setwd("/Users/rosa/projects/sales-analysis")     # macOS / Linux
getwd()                                          # confirm it took

Dwie uwagi techniczne. W Windows zapisuj ścieżki z / (albo podwójnym \\): pojedynczy \ to w napisach R znak ucieczki, więc "C:\Users" jest błędem składni. A setwd() od razu zgłasza błąd, jeśli folder nie istnieje. To najprzyjaźniejsza porażka, jaką dziś zobaczysz: nie pozwoli, żeby sesja po cichu wskazywała złe miejsce.

Procedura debugowania każdego błędu „cannot open file” jest więc taka: getwd(), żeby zobaczyć, gdzie R szuka, a potem porównanie tego z miejscem, w którym plik naprawdę leży.

list.files(): zobacz to, co widzi R

Trzecie narzędzie z zestawu wypisuje zawartość katalogu roboczego, czyli dosłownie zbiór nazw, do których może sięgnąć ścieżka względna:

Jeśli plik, który próbujesz wczytać, pojawia się w tym wyniku, read.csv("thatfile.csv") go znajdzie. Jeśli nie, żadne przepisywanie linii z read.csv nie pomoże: naprawić trzeba katalog roboczy. list.files("data") zagląda do podfolderu, a list.files(pattern = "\\.csv$") filtruje tylko pliki CSV. Gdy nazwa pliku wygląda poprawnie, ale nie da się go znaleźć, list.files() ujawnia też klasycznych winowajców: niewidoczne rozszerzenie .txt dopisane przez edytor tekstu albo Data.csv zamiast data.csv w systemie rozróżniającym wielkość liter.

Dlaczego zakodowane na sztywno setwd() się psuje

Teraz część z wyraźną opinią. Zobaczysz skrypty, które zaczynają się od:

setwd("C:/Users/me/Desktop/stuff/project3/final_FINAL")

Ta linia działa na dokładnie jednym komputerze: komputerze autora. Na twoim laptopie, na Macu kogoś z zespołu, na serwerze wydziału albo na twoim własnym komputerze po porządkach w folderach kończy się błędem w pierwszej linii. Zakodowanie ścieżki bezwzględnej wtapia układ folderów jednej osoby w kod, który ma go przetrwać.

Rozwiązaniem jest odwrócenie odpowiedzialności: nie każ skryptowi szukać folderu, tylko uruchamiaj R we właściwym folderze i używaj w skrypcie ścieżek względnych. Konkretnie:

  • Używaj projektów RStudio. Otwarcie pliku .Rproj automatycznie ustawia katalog roboczy na folder projektu, na każdym komputerze. Wtedy w skrypcie read.csv("data/sales.csv") działa u każdego, kto ma projekt.
  • Uruchamianie z terminala robi to samo: Rscript analysis.R używa jako katalogu roboczego folderu, z którego go uruchamiasz (zobacz artykuł o uruchamianiu skryptów R).
  • Pakiet here idzie o krok dalej dla chętnych: here::here("data", "sales.csv") buduje ścieżki od korzenia projektu niezależnie od tego, dokąd zawędrował katalog roboczy. Projekty i ścieżki względne pokrywają jednak większość potrzeb bez niego.

Samo setwd() nie jest złe: w trybie interaktywnym, podczas eksploracji, jest w porządku. Problemem jest konkretnie bezwzględne, zależne od komputera setwd() zapisane na początku udostępnianego skryptu.

Przestrzeń robocza: ls() i rm()

Obok pytania „w którym folderze jestem” stoi drugi element stanu sesji: przestrzeń robocza (środowisko globalne), czyli każdy obiekt utworzony w tej sesji. ls() je wypisuje, a rm() usuwa:

Ostatnie ls() wypisuje character(0), czyli pustą przestrzeń roboczą. Zaklęcie rm(list = ls()) brzmi dziwnie, dopóki go nie rozłożysz: ls() zwraca wektor tekstowy z nazwami wszystkich obiektów, a rm(list = ...) usuwa każdą nazwę z tego wektora. To kodowy odpowiednik ikony miotły w panelu Environment w RStudio.

Wiedz, czego to nie robi: pakiety załadowane przez library() zostają załadowane, opcje pozostają ustawione, a katalog roboczy się nie zmienia. Czyści obiekty i nic więcej, więc nie zastępuje ponownego uruchomienia R, gdy chcesz naprawdę czystej karty.

Czyszczenie konsoli i pułapka .RData

Czyszczenie konsoli, czyli historii poleceń i wyników na ekranie, jest kosmetyczne i niezależne od czyszczenia przestrzeni roboczej. W RStudio to Ctrl+L; w kodzie dziwaczne cat("\014") wysyła znak wysuwu strony, który większość konsol interpretuje jako „wyczyść ekran”. Żadne z nich nie dotyka twoich obiektów.

Na koniec pułapka. Gdy zamykasz R, pyta, czy „save workspace image?”, czyli czy zapisać każdy obiekt do ukrytego pliku .RData, który po cichu wczytuje się przy następnym uruchomieniu R w tym folderze. Odmów i wyłącz to na stałe (RStudio: Tools → Global Options → odznacz „Restore .RData”, ustaw „Save workspace” na Never). Przywrócona przestrzeń robocza oznacza, że sesja startuje zaśmiecona obiektami sprzed kilku dni, utworzonymi przez kod, który być może już zmieniono albo usunięto. Twój skrypt wydaje się działać, bo opiera się na przestarzałym model_v2, którego nic w pliku już nie tworzy, aż do chwili, gdy zostanie uruchomiony na czystym komputerze i się rozsypie.

Profesjonalny nawyk jest odwrotny: zaczynaj od czystej karty i uruchamiaj skrypt ponownie. Jeśli twoja analiza to skrypt, który działa od góry do dołu w świeżej sesji, jest powtarzalna z samej konstrukcji; przestrzeń robocza to jednorazowy wynik, a nie cenny stan. Często uruchamiaj R ponownie (RStudio: Session → Restart R) właśnie po to, żeby udowodnić, że skrypt wciąż radzi sobie sam.

Najważniejsze informacje

  • Ścieżki względne są rozwiązywane względem katalogu roboczego; getwd() go pokazuje, setwd() zmienia, a list.files() pokazuje, co jest osiągalne.
  • „Cannot open file” prawie zawsze oznacza, że katalog roboczy i folder z plikiem się nie zgadzają: zdiagnozuj to przez getwd() + list.files().
  • Nigdy nie zapisuj bezwzględnego setwd() w udostępnianym skrypcie: używaj projektów RStudio (albo uruchamiaj skrypt z jego folderu) i ścieżek względnych.
  • ls() wypisuje obiekty w przestrzeni roboczej; rm(x) usuwa jeden; rm(list = ls()) czyści wszystkie, a pakiety i opcje zostają.
  • Ctrl+L (albo cat("\014")) czyści tylko tekst w konsoli.
  • Nie zapisuj i nie przywracaj automatycznie .RData: zaczynaj od czystej karty i uruchamiaj skrypt ponownie. To właśnie sprawia, że twoja praca jest powtarzalna.

Dalej: wczytywanie prawdziwych danych, czyli read.csv() i spółka, teraz gdy R szuka ich we właściwym folderze.

Najczęściej zadawane pytania

Jak ustawić katalog roboczy w R?

Wywołaj setwd("path/to/folder"), żeby go zmienić, i getwd(), żeby zobaczyć bieżący. W RStudio możesz też użyć menu: Session → Set Working Directory. Ale przy wszystkim, co będziesz uruchamiać ponownie albo komuś udostępniać, wybieraj projekt RStudio (który automatycznie ustawia katalog roboczy) zamiast zakodowanej na sztywno linii setwd(): ścieżki bezwzględne psują się na każdym innym komputerze.

Jak wyczyścić środowisko w R?

rm(list = ls()) usuwa wszystkie obiekty ze środowiska globalnego: ls() wypisuje nazwy wszystkich obiektów, a rm() je usuwa. Żeby usunąć tylko jeden obiekt, użyj rm(x). Pamiętaj, że to czyści wyłącznie obiekty: załadowane pakiety zostają załadowane, a tekst w konsoli pozostaje nietknięty (do tego służy Ctrl+L w RStudio).

Dlaczego read.csv zgłasza 'cannot open file', choć plik istnieje?

Bo R rozwiązuje ścieżki względne względem swojego katalogu roboczego, a twój wskazuje gdzie indziej niż folder z plikiem. Uruchom getwd(), żeby zobaczyć, gdzie R szuka, i list.files(), żeby zobaczyć, co tam widzi. Napraw to, otwierając projekt we właściwym folderze (albo przez setwd()), a nie wklejając ścieżkę bezwzględną do skryptu.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ