Menu

כתיבת נתונים לקבצים ב-R (write.csv, saveRDS)

ייצוא מ-R: write.csv עם row.names = FALSE (תמיד), write.table למפרידים אחרים, ו-saveRDS לשמירה וטעינה בלי לאבד את הסוגים שלכם.

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

write.csv() מייצאת data frame

הוצאת data frame מ-R לקובץ שתוכנות אחרות יכולות לפתוח היא קריאה אחת:

write.csv(df, "results.csv", row.names = FALSE)

זו השורה ששווה לשנן, כולל ה-row.names = FALSE, שנצדיק עוד רגע. הארגומנט הראשון הוא ה-data frame, השני הוא שם הקובץ, והפונקציה לא מחזירה כלום: כל התפקיד שלה הוא תופעת הלוואי של יצירת הקובץ.

אפשר לראות בדיוק מה write.csv() מפיקה בלי לגעת בדיסק, כי היא מקבלת כל חיבור במקום שבו היא מצפה לשם קובץ, כולל stdout(), שפשוט מדפיס:

הנה ה-CSV שלכם: שורת כותרת, שורה אחת לכל רשומה, ערכי טקסט עטופים במירכאות, מספרים חשופים. (המירכאות הן ברירת המחדל quote = TRUE; כל קורא CSV מרכזי מטפל בהן, אז אל תיגעו בזה.) כתיבה לקובץ אמיתי היא אותה קריאה עם "results.csv" במקום stdout().

למה row.names = FALSE צריך להיות ברירת המחדל שלכם

לכל data frame יש שמות שורות, בדרך כלל פשוט המספרים 1, 2, 3..., וברירת המחדל של write.csv() היא לכתוב אותם לקובץ כעמודה ראשונה נוספת עם כותרת ריקה. הסתכלו איך נראה פלט ברירת המחדל, ומה קורה כשהקובץ הזה עושה את הדרך חזרה לתוך R:

לייצוא צמחה עמודה ראשונה בלי שם שמחזיקה "1", "2", ובייבוא מחדש read.csv() הייתה צריכה לקרוא לה בשם כלשהו, אז היא המציאה X. זו עמודת ה-X המסתורית שמבלבלת כל מתחיל: היא לא נתונים, היא המספור של השורות של R שדולף לקובץ שלכם. עשו את זה כמה פעמים במחזור של ייצוא וייבוא ותצברו X, X.1, X.2...

שמות שורות כמעט אף פעם לא נושאים מידע אמיתי, וכשהם כן, המידע שייך לעמודה אמיתית בכל מקרה. אז הפכו את row.names = FALSE לרפלקס. אפשר לטעון שזה היה צריך להיות ברירת המחדל; זה לא, מסיבות של תאימות לאחור, אז ההרגל הוא באחריותכם.

לאן הקובץ נוחת

write.csv(df, "results.csv") כותבת לתוך תיקיית העבודה של R, ואם זה לא המקום שציפיתם, נראה שהקובץ נעלם. היא לא נכשלה; הקובץ פשוט יושב בתיקייה ש-getwd() מדפיסה. זו אותה מלכודת כמו בקריאה, בתמונת ראי, ואותם שני כלים פותרים אותה:

getwd()                          # the folder your file went to
write.csv(df, "C:/Users/ada/results/out.csv", row.names = FALSE)   # or: remove all doubt

נתיבים מלאים (לוכסנים רגילים עובדים בכל פלטפורמה, כולל Windows) הופכים סקריפטים לחד-משמעיים. איך תיקיית העבודה מוגדרת ומנוהלת מוסבר ב-תיקיית העבודה.

write.table() למפרידים אחרים, ושאלת ההוספה לסוף הקובץ

write.csv() היא בעצם עטיפה דקה סביב write.table() הכללית, שמוגדרת מראש לפסיקים. קראו ל-write.table() ישירות כשצריך צורה אחרת, ובדרך כלל מופרדת בטאבים:

מופרד בטאבים, בלי מירכאות: הפורמט שכלים רבים בהמשך השרשרת מעדיפים. שימו לב שעם write.table() מגדירים הכול במפורש; היא לא יורשת את ברירות המחדל של write.csv לפסיק ולמירכאות.

דבר אחד ש-write.csv() מסרבת לעשות הוא הוספה לסוף הקובץ: העברת append = TRUE מביאה לכם אזהרה שההגדרה נזנחה, כי הוספה הייתה כותבת את שורת הכותרת שוב לאמצע הקובץ. אם באמת צריך להוסיף שורות ל-CSV קיים, למשל לתעד תוצאות לאורך כמה הרצות, רדו ל-write.table() ודכאו את הכותרת בעצמכם:

write.table(new_rows, "log.csv", sep = ",",
            append = TRUE, col.names = FALSE, row.names = FALSE)

ואם אתם ב-tidyverse, readr::write_csv(df, "out.csv") היא המקבילה של read_csv(): אותו פלט, מהירה יותר בטבלאות גדולות, והיא מלכתחילה אף פעם לא כותבת שמות שורות: ארגומנט אחד פחות לזכור.

saveRDS() ו-readRDS(): שמירה וטעינה מדויקות

CSV הוא פורמט שמאבד מידע. הוא שומר טקסט, ותו לא: עמודת Date הופכת למחרוזת "2026-08-07", factor הופך לתוויות שלו בלי סדר הרמות, מאפיינים נעלמים, ואת כל הסוגים צריך לנחש מחדש בייבוא (בדרך כלל נכון, לפעמים לא: אפסים מובילים, אנחנו מסתכלים עליכם). ו-CSV יכול להחזיק רק טבלה מלבנית אחת: למודל מותאם, לרשימה, למטריצה עם dimnames אין בכלל ייצוג ב-CSV.

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

saveRDS(df, "clean_data.rds")        # today

df <- readRDS("clean_data.rds")      # tomorrow: identical object, types intact

saveRDS() מסדרת אובייקט R אחד, כל אובייקט, בדיוק. readRDS() מחזירה אותו בית אחר בית: factors שומרים על הרמות שלהם, תאריכים נשארים תאריכים, שום דבר לא מנוחש מחדש. זה עובד על כל דבר: data frame, רשימה של data frames, מודל רגרסיה מותאם. קובץ ה-.rds הוא בינארי דחוס, ולכן בדרך כלל הוא גם קטן יותר מה-CSV. המחיר היחיד הוא ששום דבר חוץ מ-R לא יכול לפתוח אותו, וזו בדיוק הסיבה שכלל האצבע הוא: CSV כדי לשתף עם בני אדם וכלים אחרים, RDS כדי לשמור לעצמכם.

save() ו-load(), ולמה RDS בדרך כלל מנצח

תפגשו גם זוג ישן יותר. save() כותבת כמה אובייקטים עם שמות לקובץ .RData אחד, ו-load() משחזרת אותם, לתוך סביבת העבודה שלכם, תחת השמות המקוריים שלהם:

save(df, model, params, file = "session.RData")
load("session.RData")    # df, model, params silently appear

הנוחות הזאת היא הבעיה. load() מחליטה על שמות המשתנים, לא אתם: היא שותלת אובייקטים בסביבה שלכם בלי שראיתם אותם, ודורסת בשקט כל דבר שכבר היה לו אחד מהשמות האלה. חצי שנה אחר כך, אף אחד לא זוכר מה session.RData בכלל מכיל בלי לטעון אותו כדי לגלות.

ל-readRDS() יש ממשק כן: אתם בוחרים את השם (df <- readRDS(...)), שום דבר לא נדרס מאחורי הגב שלכם, וקובץ אחד פירושו אובייקט אחד. אלא אם אתם צריכים במפורש לארוז כמה אובייקטים בקובץ אחד, העדיפו RDS. (ואם כן צריך חבילה, הכנסת האובייקטים לרשימה עם שמות ושמירתה עם saveRDS() נותנת את אותה תוצאה בלי שום הפתעה.)

מה לקחת מכאן

  • write.csv(df, "out.csv", row.names = FALSE): כל הייצוא, וכן, תמיד עם row.names = FALSE.
  • עמודת ה-X המסתורית בייבוא מחדש היא שמות שורות שדלפו לקובץ; ברירת המחדל כתבה אותם, אתם לא צריכים.
  • קבצים נוחתים בתיקיית העבודה: getwd() מוצאת ייצואים "אבודים", נתיבים מלאים מונעים אותם.
  • write.table() מטפלת במפרידים אחרים ו(עם col.names = FALSE) בהוספה אמיתית לסוף הקובץ; write.csv() בכוונה לא יכולה להוסיף.
  • saveRDS() / readRDS() שומרות וטוענות כל אובייקט R בדיוק: סוגים, factors ומאפיינים נשמרים. CSV לשיתוף, RDS לעצמכם.
  • העדיפו RDS על פני save()/load(): שמות מפורשים, בלי דריסות שקטות.

הבא בתור: סוג נתונים שמגיע לו עמוד משלו לפני שהוא נושך אתכם בייבוא. תאריכים.

שאלות נפוצות

איך מייצאים data frame ל-CSV ב-R?

write.csv(df, "output.csv", row.names = FALSE). החלק row.names = FALSE חשוב: בלעדיו, R כותבת את מספרי השורות הפנימיים שלה כעמודה ראשונה נוספת, שמופיעה כעמודה מסתורית בשם X כשמישהו מייבא את הקובץ מחדש.

למה ב-CSV שייצאתי יש עמודת X כשאני קורא אותו בחזרה?

כי ברירת המחדל של write.csv היא row.names = TRUE: היא כתבה את מספרי השורות כעמודה ראשונה בלי שם, ו-read.csv קראה לעמודה הזאת X בדרך חזרה פנימה. ייצאו עם row.names = FALSE ועמודת הרפאים תיעלם.

מה ההבדל בין write.csv ל-saveRDS ב-R?

write.csv מפיקה טבלת טקסט פשוט שכל אחד יכול לפתוח, אבל היא שומרת רק טקסט: רמות של factor, סוגי Date, מאפיינים ואובייקטים שאינם טבלאיים משוטחים או הולכים לאיבוד, ואת הסוגים צריך לנחש מחדש בייבוא. saveRDS שומרת אובייקט R אחד בית אחר בית; readRDS מחזירה אותו בדיוק כמו שהיה. השתמשו ב-CSV כדי לשתף עם אחרים, וב-RDS כדי לשמור לסשנים של R שלכם.

איפה write.csv שומרת את הקובץ?

בתיקיית העבודה הנוכחית של R, אלא אם נותנים נתיב מלא. הריצו getwd() כדי לראות איפה זה: אם נראה שהקובץ שלכם נעלם, הוא יושב בתיקייה ש-getwd() מדפיסה. העברת נתיב מלא כמו "C:/Users/ada/results/out.csv" מסירה את חוסר הוודאות.

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

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

להתחיל