קודם רואים את השמות: names() ו-colnames()
שמות העמודות נמצאים במאפיין שאפשר לקרוא כמו כל וקטור. גם names() וגם colnames() מחזירות אותו עבור data frame:
אותה תשובה. ההבדל האמיתי היחיד: colnames() עובדת גם על מטריצות, names() לא, ולכן קוד כללי משתמש ב-colnames(). ב-data frames יומיומיים אפשר להחליף ביניהן.
התובנה המרכזית לכל מה שבא בהמשך: שינוי שם של עמודה הוא השמה לתוך הווקטור הזה. אין פונקציה בסיסית ייעודית; משנים את names(df) עם אותה בחירה לפי אינדקס שמשתמשים בה על כל וקטור.
שינוי שם לפי מיקום (עובד, אבל שביר)
בחרו מתוך וקטור השמות לפי מיקום והשימו ערך:
עמודה 2 היא עכשיו price. בסדר גמור לתיקון מהיר ואינטראקטיבי, ומלכודת בסקריפט. מיקומים הם הבטחה לגבי סדר העמודות, וסדר העמודות הוא הדבר הכי פחות יציב בנתונים מיובאים: ביום שבו ה-CSV שקראתם מקבל עמודה נוספת, names(df)[2] משנה את השם של העמודה הלא נכונה, בשקט. אם סקריפט משנה שמות לפי מיקום, שינוי במבנה הנתונים שובר אותו בלי הודעת שגיאה.
שינוי שם לפי שם (הדרך הבסיסית העמידה)
התאימו את השם הישן במקום לסמוך על מיקום:
קראו קודם את החלק הפנימי: names(sales) == "prc" מפיק FALSE TRUE FALSE, מסכה לוגית על וקטור השמות. בחירה לפיה בוחרת את הרשומה המתאימה, וההשמה מחליפה אותה. אם "prc" לא קיים, שום דבר לא מתאים ושום דבר לא משתנה (בלי שגיאה, אז בדקו את התוצאה). הדרך הזאת שורדת שינוי סדר, עמודות שנוספו, והעתקה לסקריפטים אחרים. שננו אותה; זו התשובה של R הבסיסית ל"איך משנים שם של עמודה".
כמה בבת אחת
החליפו את כל הווקטור כשנותנים שם לכל עמודה (נפוץ מיד אחרי ייבוא), או השתמשו ב-match() כדי לשנות שמות של תת-קבוצה נבחרת:
match(old, names(df)) מחזירה את המיקומים של השמות הישנים, כך שהשמות החדשים נוחתים בדיוק איפה שהישנים היו: בטוח מבחינת סדר, כמו הדרך לשם יחיד. אם שם ישן כלשהו חסר, match() מחזירה NA וההשמה נכשלת בשגיאה, וזה בדיוק אופן הכישלון שרוצים: רועש.
setNames() לשרשראות
כל הדרכים שלמעלה משנות משתנה בשני שלבים. setNames(object, names) מחזירה עותק עם שמות חדשים בביטוי אחד, וזה מה ששרשרת צריכה:
שימושי כשפונקציה מחזירה טבלה בלי שמות או עם שמות גרועים ורוצים לתקן אותה בתוך השורה, read_something() |> setNames(c("id", "value")), בלי משתנה זמני.
הדרך של dplyr: rename() ו-rename_with()
rename() של dplyr מקבלת זוגות new = old, השם החדש קודם, וכולם מתבלבלים בזה פעם אחת (קוד סטטי; סביבת ההרצה כאן מריצה רק R בסיסית):
library(dplyr)
sales |> rename(price = prc, qty = q)
שמות ישנים שהקריאה לא נוגעת בהם נשמרים כמו שהם, ושם ישן עם שגיאת כתיב הוא שגיאה ממשית ולא פעולה שקטה שלא עושה כלום: שיפור אמיתי לעומת הדרך הבסיסית. כדי לשנות שמות לפי כלל ולא לפי זוג, rename_with() מפעילה פונקציה על השמות:
sales |> rename_with(toupper) # every column
sales |> rename_with(toupper, starts_with("p")) # just some
ראו את המבוא ל-dplyr כדי להבין איך הן משתלבות במשפחת הפעלים.
ניקוי כותרות מבולגנות מקבצים מיובאים
כותרות CSV אמיתיות מגיעות בצורה "Order ID", "unit.price ($)", "2024 Total": שמות עם רווחים וסמלים שמכריחים לעטוף אותם בגרש הפוך בכל מקום. make.names() של R הבסיסית ממירה כל וקטור של תווים לשמות R תקינים:
תקין, אבל מכוער בדרכו שלו (X2024.Total). לכן צוותים רבים מתקננים על clean_names() של החבילה janitor, שמפיקה snake_case מסודר (order_id, unit_price, x2024_total) בקריאה אחת: df |> janitor::clean_names(). אם אתם מייבאים קבצים מבולגנים כל שבוע, היא מחזירה את ההשקעה מיד.
מה לקחת מכאן
- שמות העמודות הם פשוט וקטור: קוראים אותם עם
names()/colnames(), ומשנים על ידי השמה לתוכו. names(df)[2] <- "new"שביר;names(df)[names(df) == "old"] <- "new"היא הדרך ששווה לשנן.match()משנה כמה שמות לפי שם;setNames()משנה שמות בתוך שרשרת.rename(new = old)של dplyr נכשלת על שמות חסרים (טוב), ו-rename_with()משנה שמות לפי כלל.- לכותרות מבולגנות מקבצים מיובאים:
make.names()ב-R הבסיסית,janitor::clean_names()לתוצאות יפות.
הבא בתור: מיון. sort() לווקטורים, הטריק של order() ל-data frames, ו-arrange().
שאלות נפוצות
איך משנים שם של עמודה ב-R?
הדרך הבסיסית העמידה היא התאמה לפי שם: names(df)[names(df) == "old"] <- "new". היא מוצאת את העמודה שנקראת old בכל מקום שבו היא נמצאת ומשנה את שמה. ב-dplyr זה rename(df, new = old). שימו לב לסדר: השם החדש קודם.
מה ההבדל בין names() ל-colnames()?
ב-data frame אין הבדל מעשי: שתיהן קוראות ומגדירות את שמות העמודות. colnames() עובדת גם על מטריצות (שם names() לא עובדת), ולכן קוד שאמור לטפל בשניהם נוטה להשתמש ב-colnames(). ב-data frames רגילים, השתמשו במה שנוח לכם.
איך משנים שם של עמודה לפי מיקום ב-R?
השימו ערך לתוך וקטור השמות במיקום הזה: names(df)[2] <- "price" משנה את שם העמודה השנייה. זה עובד, אבל שביר: ביום שבו נוספת עמודה או שה-CSV משנה את סדר העמודות, מיקום 2 הוא עמודה אחרת. העדיפו שינוי שם לפי שם.
איך משנים שמות של כמה עמודות בבת אחת ב-R?
השימו וקטור מלא: names(df) <- c("id", "name", "price") מחליף את כל השמות לפי הסדר. כדי לשנות רק כמה נבחרות לפי שם, השתמשו ב-match(): names(df)[match(c("old1", "old2"), names(df))] <- c("new1", "new2"). ב-dplyr: rename(df, new1 = old1, new2 = old2).