Menu

תיקיית העבודה ב-R: setwd(), getwd() וניקוי סביבת העבודה

איפה R מחפשת קבצים ואיך שולטים בזה: getwd(), setwd(), list.files(), ניקוי הסביבה עם rm(list = ls()), ולמה השמירה האוטומטית של .RData היא מלכודת.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

מהי תיקיית העבודה

כל סשן R רץ "בתוך" תיקייה אחת בדיוק: תיקיית העבודה. בכל פעם שמשתמשים בנתיב יחסי, נתיב שלא מתחיל מהשורש של מערכת הקבצים, R מפענחת אותו ביחס לתיקייה הזאת. read.csv("data.csv") לא אומר "מצא את data.csv איפשהו במחשב שלי"; הוא אומר "פתח את הקובץ שנקרא data.csv בתיקיית העבודה".

העובדה הזאת לבדה מסבירה את השגיאה הנפוצה ביותר של מתחילים ב-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

הקובץ קיים, רק לא בתיקייה ש-R מסתכלת עליה כרגע. אין שום בעיה ב-קריאה ל-read.csv שלכם; תיקיית העבודה של הסשן והמיקום של הקובץ לא מסכימים. שתי הפונקציות שלהלן הופכות את זה מתעלומה לאבחון של עשר שניות.

getwd() ו-setwd()

getwd() (get working directory) אומרת לכם איפה R מחפשת עכשיו:

הריצו את זה ותראו נתיב מוחלט: התיקייה שהסשן הזה מעוגן אליה. setwd() (set working directory) משנה אותה:

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

שתי הערות טכניות. ב-Windows, כתבו נתיבים עם / (או עם \\ כפול): \ בודד הוא תו בריחה בתוך מחרוזות R, ולכן "C:\Users" היא שגיאת תחביר. ו-setwd() נכשלת מיד אם התיקייה לא קיימת, וזה הכישלון הידידותי ביותר שתקבלו כל היום: היא לא יכולה להשאיר אתכם בשקט מצביעים למקום הלא נכון.

שגרת הדיבוג לכל שגיאת "cannot open file" היא לכן: getwd() כדי לראות איפה R מחפשת, ואז השוואה למקום שבו הקובץ נמצא באמת.

list.files(): לראות את מה ש-R רואה

הכלי השלישי בערכה מציג את התוכן של תיקיית העבודה, כלומר בדיוק את קבוצת השמות שנתיב יחסי יכול להגיע אליהם:

אם הקובץ שאתם מנסים לקרוא מופיע בפלט הזה, read.csv("thatfile.csv") תמצא אותו. אם לא, שום כמות של הקלדה מחדש של שורת ה-read.csv לא תעזור: תיקיית העבודה היא הדבר שצריך לתקן. list.files("data") מציצה לתוך תת-תיקייה, ו-list.files(pattern = "\\.csv$") מסננת לקובצי CSV בלבד. כששם קובץ נראה נכון אבל לא נמצא, list.files() חושפת גם את האשמים הקלאסיים: סיומת .txt בלתי נראית שעורך טקסט הוסיף, או Data.csv מול data.csv במערכת שרגישה לאותיות גדולות וקטנות.

למה setwd() מקודד נשבר

ועכשיו החלק עם הדעה. תראו סקריפטים שנפתחים כך:

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

השורה הזאת עובדת במחשב אחד בדיוק: של מי שכתב אותה. במחשב הנייד שלכם, ב-Mac של עמית, בשרת של המחלקה, או במחשב שלכם אחרי סידור מחדש, היא נכשלת בשורה 1. קידוד של נתיב מוחלט אופה את מבנה התיקיות של אדם אחד לתוך קוד שאמור להאריך ימים אחריו.

התיקון הוא להפוך את האחריות: אל תגרמו לסקריפט למצוא את התיקייה: הפעילו את R בתיקייה הנכונה, והשתמשו בנתיבים יחסיים בתוך הסקריפט. בפועל:

  • השתמשו ב-RStudio Projects. פתיחת קובץ .Rproj מגדירה את תיקיית העבודה לתיקיית הפרויקט אוטומטית, בכל מחשב. בתוך הסקריפט, read.csv("data/sales.csv") עובדת אז לכל מי שיש לו את הפרויקט.
  • הרצה מטרמינל עושה את אותה עבודה: Rscript analysis.R משתמש בתיקייה שממנה מפעילים אותו כתיקיית העבודה (ראו הרצת סקריפטים של R).
  • החבילה here הולכת צעד אחד קדימה למי שרוצה: here::here("data", "sales.csv") בונה נתיבים משורש הפרויקט בלי קשר לאן שתיקיית העבודה נדדה, אבל Projects יחד עם נתיבים יחסיים מכסים את רוב הצרכים גם בלעדיה.

setwd() עצמה לא רעה: היא בסדר בעבודה אינטראקטיבית, בזמן חקירה. הבעיה היא ספציפית ב-setwd() מוחלט, תלוי מחשב, שנשמר בראש סקריפט משותף.

סביבת העבודה: ls() ו-rm()

לצד "באיזו תיקייה אני נמצא" יושב החלק השני של מצב הסשן: סביבת העבודה (הסביבה הגלובלית), כל אובייקט שיצרתם בסשן הזה. ls() מציגה אותם, rm() מסירה אותם:

ה-ls() האחרון מדפיס character(0): סביבת עבודה ריקה. הלחש rm(list = ls()) נקרא מוזר עד שמפרקים אותו: ls() מחזירה את וקטור התווים של כל שמות האובייקטים, ו-rm(list = ...) מוחקת כל שם בווקטור הזה. זה המקבילה בקוד לאייקון המטאטא של RStudio בחלונית Environment.

דעו מה זה לא עושה: חבילות שנטענו עם library() נשארות טעונות, הגדרות נשארות מוגדרות, ותיקיית העבודה נשארת במקומה. זה מנקה אובייקטים, ותו לא, ולכן זה לא תחליף להפעלה מחדש של R כשרוצים דף נקי באמת.

ניקוי הקונסולה, ומלכודת ה-.RData

ניקוי הקונסולה, היסטוריית הפקודות והפלט, הוא קוסמטי ונפרד מניקוי סביבת העבודה. ב-RStudio זה Ctrl+L; בקוד, cat("\014") המוזר שולח את תו ה-form-feed, שרוב הקונסולות מפרשות כ"נקה מסך". אף אחד מהם לא נוגע באובייקטים שלכם.

ולבסוף, המלכודת. כשיוצאים מ-R היא מציעה "save workspace image?", כלומר לכתוב כל אובייקט לקובץ .RData מוסתר שנטען מחדש בשקט בפעם הבאה שמפעילים את R באותה תיקייה. סרבו, וכבו את זה לצמיתות (ב-RStudio: Tools → Global Options → בטלו את הסימון של "Restore .RData", והגדירו את "Save workspace" ל-Never). סביבת עבודה משוחזרת פירושה שהסשן שלכם מתחיל מזוהם באובייקטים מלפני כמה ימים, שנוצרו בקוד שאולי ערכתם או מחקתם מאז. הסקריפט שלכם נראה עובד, כי הוא נשען על model_v2 מיושן ששום דבר בקובץ כבר לא יוצר, עד לרגע שבו הוא רץ במחשב נקי וקורס.

ההרגל המקצועי הוא ההפך: התחילו נקי, והריצו את הסקריפט מחדש. אם הניתוח שלכם הוא סקריפט שרץ מההתחלה ועד הסוף בסשן חדש, הוא ניתן לשחזור מעצם הבנייה שלו; סביבת העבודה היא פלט חד-פעמי, אף פעם לא מצב יקר ערך. הפעילו את R מחדש לעיתים קרובות (ב-RStudio: Session → Restart R) בדיוק כדי להוכיח שהסקריפט שלכם עדיין עומד בזכות עצמו.

מה לקחת מכאן

  • נתיבים יחסיים מפוענחים ביחס לתיקיית העבודה; getwd() מציגה אותה, setwd() משנה אותה, list.files() מראה למה אפשר להגיע.
  • "Cannot open file" אומר כמעט תמיד שתיקיית העבודה והתיקייה של הקובץ לא מסכימות: אבחנו עם getwd() ו-list.files().
  • לעולם אל תשמרו setwd() מוחלט בסקריפט משותף: השתמשו ב-RStudio Projects (או הריצו את הסקריפט מהתיקייה שלו) ובנתיבים יחסיים.
  • ls() מציגה את האובייקטים בסביבת העבודה; rm(x) מסירה אחד; rm(list = ls()) מנקה את כולם, וחבילות והגדרות נשארות.
  • Ctrl+L (או cat("\014")) מנקה רק את הטקסט בקונסולה.
  • אל תשמרו ואל תשחזרו .RData אוטומטית: התחילו נקי והריצו את הסקריפט מחדש, וזה מה שהופך את העבודה שלכם לניתנת לשחזור.

הבא בתור: קריאת נתונים אמיתיים. read.csv() וחברותיה, עכשיו כש-R מחפשת בתיקייה הנכונה כדי למצוא אותם.

שאלות נפוצות

איך מגדירים את תיקיית העבודה ב-R?

קראו ל-setwd("path/to/folder") כדי לשנות אותה ול-getwd() כדי לראות את הנוכחית. ב-RStudio אפשר גם להשתמש בתפריט: Session → Set Working Directory. אבל לכל דבר שתריצו שוב או תשתפו, העדיפו RStudio Project (שמגדיר את תיקיית העבודה אוטומטית) על פני שורת setwd() מקודדת: נתיבים מוחלטים נשברים בכל מחשב אחר.

איך מנקים את הסביבה ב-R?

rm(list = ls()) מסירה כל אובייקט מהסביבה הגלובלית: ls() מציגה את שמות כל האובייקטים ו-rm() מוחקת אותם. כדי להסיר אובייקט אחד בלבד, השתמשו ב-rm(x). שימו לב שזה מנקה רק אובייקטים: חבילות טעונות נשארות טעונות, והטקסט בקונסולה לא משתנה (בשביל זה יש Ctrl+L ב-RStudio).

למה read.csv אומרת 'cannot open file' כשהקובץ קיים?

כי R מפענחת נתיבים יחסיים ביחס לתיקיית העבודה שלה, ושלכם מצביעה למקום אחר מהתיקייה שמכילה את הקובץ. הריצו getwd() כדי לראות איפה R מחפשת ו-list.files() כדי לראות מה היא רואה שם. תקנו על ידי פתיחת הפרויקט בתיקייה הנכונה (או setwd()), לא על ידי הדבקת נתיב מוחלט לתוך הסקריפט.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל