Menu

Factors ב-R: נתונים קטגוריאליים, רמות ומלכודות נפוצות

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

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

מה factor באמת

Factor הוא התשובה של R לנתונים קטגוריאליים: ערכים שמגיעים מתפריט קבוע של אפשרויות: קבוצות טיפול, תשובות בסקר, מידות של חולצות. בהדפסה הוא נראה כמו וקטור תווים, אבל הוא לא. בפנים, factor הוא וקטור של קודים שלמים ועוד טבלת חיפוש של תוויות שנקראות רמות (levels):

ההדפסה מציגה את התוויות, ואז שורת Levels: שמפרטת את התפריט. as.integer() חושפת את המנגנון: הקודים חוזרים כ-3 1 3 2, כי כל ערך הוא בעצם אינדקס לטבלת הרמות, והרמות ממוינות לפי האלף-בית כברירת מחדל (large, medium, small), לא בסדר שבו הנתונים הגיעו. לכן small הוא קוד 3 ו-large הוא קוד 1, וזה לא אינטואיטיבי לאף אחד. זכרו את ברירת המחדל האלפביתית הזו; היא עומדת מאחורי שתיים מהמלכודות בהמשך.

למה לטרוח עם העיצוב הדו-שכבתי הזה במקום מחרוזות רגילות? כי הסטטיסטיקה צריכה אותו. מודל לא יכול להכפיל "small" במקדם, אבל הוא יכול לקודד שלוש רמות ידועות כעמודות של 0 ו-1. פונקציות כמו lm(), glm(), table() והמנגנון שמאחורי ANOVA נשענות כולן על factors כדי לדעת שמשתנה הוא קטגוריאלי, מהי הקבוצה המלאה של הקטגוריות (כולל כאלה שלא מופיעות בנתונים), ואיזו קטגוריה היא קו הבסיס. וקטורי תווים רגילים לא נושאים שום דבר מזה.

יצירת factors: levels, labels ו-table()

כברירת מחדל factor() לוקחת את הערכים השונים שהיא מוצאת וממיינת אותם לפי האלף-בית לרמות. לעיתים קרובות תרצו שליטה גם על הקבוצה וגם על הסדר: העבירו levels =:

עכשיו הרמות מסודרות לפי סדר המידות הטבעי, ו-table(), ספירת השכיחויות בשורה אחת שתשתמשו בה כל הזמן עם factors, מדווחת על ספירות גם היא בסדר הזה. nlevels() סופרת קטגוריות.

levels = נותן לכם עוד שני דברים. ערכים בנתונים שלא נמצאים ברשימת הרמות שלכם הופכים ל-NA (טוב: שגיאות הקלדה צצות במקום להפוך לקטגוריה משלהן). ורמות עם אפס הופעות עדיין קיימות, כך שסיכום של תשובות בסקר מציג "strongly disagree: 0" במקום להעמיד פנים שהאפשרות לא הייתה קיימת.

labels = משנה את שמות הרמות בזמן היצירה, וזה שימושי כשהנתונים הגולמיים משתמשים בקודים:

ו-as.factor(x) היא הממירה המהירה לווקטור קיים כשברירות המחדל בסדר.

Factors מסודרים לנתונים סודרים

Factors רגילים מתייחסים לקטגוריות כלא מסודרות: "red" לא קטן מ-"blue". אבל לחלק מהסולמות הקטגוריאליים יש דירוג אמיתי: low/medium/high, disagree/neutral/agree. הצהירו על כך עם ordered = TRUE:

ההדפסה מציגה עכשיו Levels: low < medium < high, ואופרטורי השוואה עובדים: אפשר לשאול אם דירוג אחד גבוה מאחר, או לסנן לכל מה שב-"medium" ומעלה. בשני המקרים factor לא מסודר היה נותן שגיאה (טוב, אזהרות וערכי NA). Factors מסודרים משנים גם את האופן שבו מודלים מקודדים את המשתנה (ניגודים פולינומיאליים במקום משתני דמה), וזה בדרך כלל מה שרוצים למשתנים מסבירים סודרים.

השתמשו ב-ordered = TRUE רק כשהדירוג אמיתי. קידוד של קבוצות רגילות כמסודרות משנה את פלט המודל בדרכים שקל לפרש לא נכון.

רמת הייחוס ו-relevel()

הרמה הראשונה של factor מיוחדת: פונקציות מודל מתייחסות אליה כאל קטגוריית הייחוס, קו הבסיס שמולו נמדד המקדם של כל רמה אחרת. מכיוון שסדר הרמות כברירת מחדל הוא אלפביתי, קו הבסיס שלכם נבחר על ידי האלף-בית אלא אם אתם מתערבים, ו-"control" שמפסיד ל-"aspirin" לפי סדר האלף-בית אינו החלטה מדעית.

relevel() מקדמת רמה למקום הראשון:

לפני: control ראשון רק במזל אלפביתי. אחרי relevel(..., ref = "control") הוא ראשון בכוונה. ברגרסיה לינארית עם המשתנה המסביר הזה, המקדם של treatment עונה עכשיו על "במה הטיפול שונה מהביקורת?", השאלה ששאלתם באמת. בכל פעם שמקדמים קטגוריאליים של מודל נראים מבלבלים, בדקו קודם את רמת הייחוס.

(לסידור מחדש מלא, לא רק של המקום הראשון, העבירו שוב וקטור levels = שלם ל-factor().)

המלכודת הקלאסית: המרת factor למספר

לפעמים מספרים מגיעים כ-factors, בדרך כלל עמודה בקובץ CSV שהכילה ערך תועה לא מספרי. ההמרה חזרה נראית מובנת מאליה ומשתבשת באופן בלתי נשכח:

as.numeric(f) מחזירה 2 1 3. לא 20, 10, 30, אלא את קודי הרמות. הרמות ממוינות לפי האלף-בית ל-"10", "20", "30", כך ש-"20" הוא רמה 2 ומומר ל... 2. בלי שגיאה, בלי אזהרה, מספרים שלמים קטנים שנראים סבירים מחליפים בשקט את הנתונים שלכם. מחקרים נמשכו בגלל המלכודת הזו.

הדרך הנכונה עוברת דרך character: as.numeric(as.character(f)) משחזרת קודם את התוויות כטקסט, ואז מפענחת את הטקסט כמספרים: 20 10 30. חרטו את הביטוי הזה בזיכרון: המרה של factor למספר תמיד עוברת דרך as.character().

droplevels() והסיפור של stringsAsFactors

חיתוך של factor שומר את כל קבוצת הרמות, גם לקטגוריות שכבר לא מופיעות:

אחרי סינון large החוצה, table() עדיין מדווחת עליו, עם ספירה של 0. לפעמים זה בדיוק נכון (אתם רוצים שהקטגוריה הריקה תהיה גלויה). כשלא, קבוצות עם ספירה אפס מעמיסות על גרפים ויכולות לשבור ניתוחים מרובדים, ו-droplevels() משליכה רמות ללא תצפיות.

הערה היסטורית שתצטרכו כשתקראו קוד ישן או תשובות ב-Stack Overflow: לפני R 4.0 (2020), data.frame() ו-read.csv() המירו כל עמודת תווים ל-factor באופן אוטומטי: stringsAsFactors = TRUE היה ברירת המחדל. עשור של מדריכים זרוע בפתרונות עוקפים ל-factors שאף אחד לא ביקש. מאז R 4.0 ברירת המחדל היא FALSE: מחרוזות נשארות מחרוזות, ואתם יוצרים factors בכוונה, במקום שבו משתנה ב-data frame שלכם הוא באמת קטגוריאלי. זה ההרגל הנכון: factors מפורשים, בכוונה, עם רמות שבחרתם.

מה לקחת מכאן

  • Factor = קודים שלמים + תוויות רמות; זה מה שאומר לפונקציות סטטיסטיות שמשתנה הוא קטגוריאלי.
  • שלטו בקבוצת הקטגוריות ובסדר שלהן עם levels =, שנו שמות עם labels =, ספרו עם table().
  • ordered = TRUE מאפשר השוואות לסולמות סודרים באמת.
  • הרמה הראשונה היא קו הבסיס של המודל: קבעו אותה בכוונה עם relevel(f, ref = ...).
  • לעולם אל תפעילו as.numeric(f) ישירות: תמיד as.numeric(as.character(f)).
  • droplevels() מנקה רמות שלא בשימוש אחרי חיתוך; מאז R 4.0 מחרוזות נשארות מחרוזות אלא אם אתם יוצרים factors בעצמכם.

הבא בתור: data frames, המקום שבו factors, מספרים וטקסט חיים יחד כעמודות של טבלה אחת.

שאלות נפוצות

מה זה factor ב-R?

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

איך ממירים factor למספר ב-R?

עוברים דרך character: as.numeric(as.character(f)). קריאה ישירה ל-as.numeric(f) מחזירה את קודי הרמות הפנימיים (1, 2, 3, ...), לא את הערכים שהתוויות מציגות, כך ש-factor שמציג "20" יכול לחזור כ-2. זה אחד הבאגים השקטים הנפוצים ביותר ב-R.

מה עושה relevel() ב-R?

היא מעבירה רמה שבחרתם למקום הראשון: relevel(group, ref = "control"). הרמה הראשונה היא קטגוריית הייחוס (קו הבסיס) שפונקציות מודל כמו lm() ו-glm() משוות אליה כל רמה אחרת, ולכן בחירה מכוונת שלה גורמת למקדמי הרגרסיה לומר את מה שאתם מתכוונים.

למה ה-factor שלי עדיין מציג רמות שהסרתי?

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

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

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

להתחיל