סוגי הנתונים ב-R
לכל ערך ב-R יש אחד מתוך קבוצה קטנה של סוגים אטומיים. ארבעה מהם עושים כמעט את כל העבודה:
- double: מספרים עשרוניים:
3.14,-2,1e6. לזה R מתכוונת כשהיא אומרת "numeric", וזו ברירת המחדל לכל מספר שאתם מקלידים. - integer: מספרים שלמים שמאוחסנים במדויק, ונכתבים עם הסיומת
L:42L. - character: טקסט במירכאות:
"hello". - logical: שני ערכי האמת
TRUEו-FALSE(ועודNA, הערך החסר; ראו ערכים חסרים).
יש גם complex (2 + 3i) לחישובים מזדמנים של עיבוד אותות; אפשר לעבור שנים בלי להזדקק לו. typeof() אומרת לכם מאיזה סוג ערך מסוים:
שימו לב לשורה הראשונה: מספר רגיל הוא double גם אם הוא נראה שלם. typeof(42) הוא "double"; רק 42L הוא integer. בניתוח יומיומי ההבדל כמעט לא משנה, R ממירה ביניהם בשקט, אבל הוא מסביר הרבה פלט מבלבל של typeof().
typeof() מול class(): למה הן לא מסכימות
ב-R יש שתי פונקציות ששתיהן נראות כאילו הן עונות על "מה זה?", והן עונות על שאלות שונות במעט.
typeof()מדווחת על סוג האחסון: איך הערך יושב בזיכרון.class()מדווחת על סוג ההתנהגות: התווית שבה מנגנון בחירת המתודות של R משתמש כדי להחליט, למשל, איזהprintאוsummaryלהריץ.
עבור ערכים פשוטים התשובות שונות רק באוצר המילים:
typeof() אומרת double (האחסון), class() אומרת numeric (ההתנהגות). עבור מבנים הפער גדל:
המטריצה מאוחסנת כווקטור integer רגיל, אבל היא מתנהגת כמטריצה: class() היא מה שאומר ל-R להדפיס אותה כרשת. אותה חלוקה מופיעה ב-data frames (typeof אומרת "list", class אומרת "data.frame") ובתאריכים (typeof אומרת "double", class אומרת "Date").
הכלל המעשי: השתמשו ב-class() כשאתם רוצים לדעת מה משהו הוא במובן היומיומי, וב-typeof() כשאתם מנפים באגים במה ש-R עושה מתחת למכסה המנוע.
בדיקת סוגים עם is.*()
לכל סוג יש פרדיקט תואם שמחזיר TRUE או FALSE, שימושי בתוך פונקציות שצריכות לוודא את הקלט שלהן:
מלכודת אחת שכדאי להכיר: is.numeric() מחזירה TRUE גם עבור doubles וגם עבור integers (שניהם מספרים), אבל is.integer() בודקת את האחסון, ולכן היא FALSE עבור 42 רגיל:
אם אי פעם הופתעתם ש-is.integer(7) הוא FALSE עבור מספר שהוא כמובן שלם במובן המתמטי, זו הסיבה. 7 הוא double; 7L הוא integer.
המרת סוגים עם as.*()
המרה מפורשת משתמשת במשפחת as.*, פונקציה אחת לכל סוג יעד:
שתי התנהגויות שכדאי לזכור. as.integer() קוטעת לכיוון האפס במקום לעגל: 7.9 הופך ל-7. וכשהמרה חסרת היגיון, R לא זורקת שגיאה; היא מחזירה NA ומוציאה אזהרה:
הריצו את זה ותראו NA ועוד אזהרה "NAs introduced by coercion". זה שימושי באמת: המירו עמודה שלמה של טקסט מבולגן למספרים, והערכים שאי אפשר לפענח יהפכו ל-NA במקום להפיל את הסקריפט. אבל זה גם אומר ש-NA שקט יכול לחמוק לתוך הנתונים שלכם. כשהמרה חשובה, בדקו אחריה אם הופיעו ערכי NA חדשים.
ערכים לוגיים מומרים למספרים וממספרים כמו שהייתם מקווים: as.numeric(TRUE) הוא 1, as.logical(0) הוא FALSE. זו הסיבה ש-sum() של וקטור לוגי סופרת את ה-TRUE:
כפיית סוג מרומזת: כלל הסוג האחד בווקטורים
וקטור אטומי ב-R יכול להכיל סוג אחד בלבד. שלבו ערכים מעורבים עם c(), ו-R תקדם בשקט הכול לסוג הגמיש ביותר שקיים, לפי סולם קבוע:
logical → integer → double → character
הערכים הלוגיים הפכו ל-1 ו-0, ה-integers הפכו ל-doubles, ובשורה האחרונה הכול הפך לטקסט: character תמיד מנצח, כי כל ערך אפשר לכתוב כמחרוזת. אפשר לוודא עם typeof():
כפיית סוג היא המקור מספר אחת לבאגים מסוג "למה העמודה שלי היא טקסט?": מחרוזת "N/A" תועה אחת בעמודה של מספרים כופה על כל הווקטור להיות character. כשזה קורה, תקנו קודם את הערך הבעייתי, ואז המירו חזרה עם as.numeric().
מה לקחת מכאן
- ארבעה סוגים עיקריים: double ("numeric"), integer (
42L), character, logical. typeof()= איך זה מאוחסן;class()= איך זה מתנהג.3.14הואdoubleשמתנהג כ-numeric.- בדקו עם
is.numeric()וחברותיה; המירו עםas.numeric()וחברותיה: המרות שנכשלו נותנותNAעם אזהרה, לא שגיאה. - וקטורים מכילים סוג אחד בלבד; ערבוב כופה סוג לאורך logical → integer → double → character.
הבא בתור: מבט מקרוב על הסוגים המספריים: עיגול, פונקציות מתמטיות, וההפתעות של נקודה צפה שמשותפות לכל השפות.
שאלות נפוצות
מהם סוגי הנתונים הבסיסיים ב-R?
הסוגים האטומיים הם double (מספרים עשרוניים, מה ש-R מכנה "numeric"), integer (מספרים שלמים שנכתבים עם הסיומת L, כמו 42L), character (טקסט במירכאות), logical (TRUE/FALSE), ו-complex שכמעט לא משתמשים בו. כל דבר גדול יותר, וקטורים, data frames, רשימות, בנוי מהם.
מה ההבדל בין typeof() ל-class() ב-R?
typeof() מדווחת איך ערך מאוחסן בזיכרון (הסוג ברמה הנמוכה שלו); class() מדווחת איך הערך מתנהג, וזה קובע אילו מתודות R מפעילה. עבור מספר עשרוני רגיל הן חלוקות רק בניסוח: typeof(3.14) הוא "double" ואילו class(3.14) הוא "numeric", ועבור מבנים כמו data frames, typeof() אומרת "list" ו-class() אומרת "data.frame".
איך ממירים סוגים ב-R?
משתמשים במשפחת as.*: as.numeric("3.5") נותנת 3.5, as.character(42) נותנת "42", as.integer(7.9) קוטעת ל-7. כשהמרה בלתי אפשרית, R מחזירה NA ומתריעה באזהרה במקום בשגיאה: as.numeric("abc") הוא NA.
מה זו כפיית סוג (coercion) ב-R?
כשמשלבים סוגים שונים בווקטור אחד, R ממירה בשקט הכול לסוג הגמיש ביותר, לפי הסדר logical → integer → double → character. לכן c(1, 2, "three") הופך לווקטור תווים: "1" "2" "three".