הקדמה

בשיעורים הקודמים למדנו את סוגי המשתנים השונים של R ואיך לבצע מנפולציות על טבלאות נתונים בעזרת ספריות חיצוניות.

בשיעור הזה נתרכז במספר משתנים חשובים שדורשים יותר תשומת לב.


מטרות

מטרת השיעור הזה הוא ללמוד על השימושים של המשתנים הבאים:

  • Factors
  • קיבוץ משתנים
  • שימוש בחבילת questionr
  • פקודות לשינוי סוג משתנה
  • תאריכים

Factor

משתנה פקטור הוא משתנה קטגוריאלי המייצג רמות שונות של משתנה לעומת משתנה רציף או נומרי אחר.

למשתני פקטור יש שני שימושים עיקריים:

  1. משמש כסוג של פורמט למשתנה מקודד
  2. התייחסות למשתנה כקטגוריאלי בניתוחים סטטיסטים מתקדמים

כפי שלמדנו, מאחורי הקלעים, factor נשמר כ integer אבל מקבל ביטוי בפלט כ character


סוגי פקטורים

פקטור יכול להיות מהסוגים הבאים:

  • משתנה קטגוריאלי - Factors - i.e. yes/no, male/female
  • משתנה אורדינאלי - Ordered Factors - high/medium/low

הגדרת משתנה כפקטור

על מנת להגדיר משתנה כפקטור נשתמש בפקודת factor עם הסנטקס הבא:

factor(x , levels = c(LevelValues), labels = c(“LabelValues”), exclude = NA, ordered = is.ordered(x), nmax = NA)

שימו לב לאופציה להשמיט ערכים חסרים או לכלולל אותם כאחד מרמות הפקטור בעזרת השמת NULL באופציה exclude

הפקודה levels מחזירה או משנה את קטגוריות המשתנה

למשל, על מנת לשנות משתנה לקטגוריאלי :

Santander_sample <- Santander_sample %>%
                      mutate(
                      ind_cc_fct = factor(ind_cc
                      , levels = c(0, 1, NA)
                      , labels = c("no", "yes", "missing")
                      , exclude = NULL))

levels(Santander_sample$ind_cc_fct)
## [1] "no"      "yes"     "missing"
summary(Santander_sample$ind_cc_fct)
##      no     yes missing 
##   98765    1206      29

ואם נרצה שיהיה משמעות לסדר :

Santander_sample <- Santander_sample %>%
                      mutate(
                      segmento_fct = factor(segmento)
                      , ordered = TRUE
                      , exclude = NULL)

levels(Santander_sample$segmento_fct)
## [1] "01 - TOP"           "02 - PARTICULARES"  "03 - UNIVERSITARIO"
summary(Santander_sample$segmento_fct)
##           01 - TOP  02 - PARTICULARES 03 - UNIVERSITARIO 
##               7934              65854              26212

שימו לב: כברירת מחדל, המשתנה מקודד לפי סדר הופעת הערכים

וכמו בדוגמא הקודמת, כל הפרמטרים למעט העמודה הם אופציונאלים


כמה נקודות חשובות שצריך לקחת בחשבון :

  • ברגע שמגדירים פקטור , המשתנה לא יכול לקבל ערכים אחרים
  • גם אם אין את רמת המשתנה, הרמות נשארות עד שמוחקים אותם בעזרת droplevels
# This won't work:
# Santander_sample$segmento_fct[5] <- "עגבניה"

Santander_sample <- Santander_sample %>% filter(segmento_fct !="03 - UNIVERSITARIO")
summary(Santander_sample$segmento_fct)
##           01 - TOP  02 - PARTICULARES 03 - UNIVERSITARIO 
##               7934              65854                  0
Santander_sample$segmento_fct <- droplevels(Santander_sample$segmento_fct)
summary(Santander_sample$segmento_fct)
##          01 - TOP 02 - PARTICULARES 
##              7934             65854

פקודות עזר מספריות חיצוניות

יש כמה חבילות שמנסות להקל על ביצוע פעולות עם פקטורים.

  • חבילת dplyr יש פקודת recode
  • חבילת forcats עוזרת לשנות סדר וקידוד של פקטורים
  • חבילת haven המייבא נתונים מ SAS ביחד עם הפורמטים שלהם

עוד חבילות ראויות לציון שיכולות לייעל את העבודה עם פקטורים הם חבילת memisc וחבילת Hmisc ועוד…


פקודת recode

פקודת recode ופקודת recode_factor מאפשרות קידוד מחדש של משתנה פקטור באותו סינטקס של dplyr

Santander_sample <- Santander_sample %>%
                      mutate(
                      ind_cc_fct = recode_factor(ind_cc
                      , "0" = "no"
                      , "1" = "yes"
                      , .missing = "missing"
                      ))

levels(Santander_sample$ind_cc_fct)
## [1] "no"      "yes"     "missing"
summary(Santander_sample$ind_cc_fct)
##      no     yes missing 
##   72629    1137      22

חבילת forcats

חבילת forcats היא חלק מה tidyverse ומאפשרת סידור מחדש של המשתנה הקטגוריאלי בהתאם לצרכי התצוגה ואיגוד רמות של משתנה בהתאם לצורך.

הפקודות העיקריות בה הן:

  • fct_inorder - המסדר מחדש פקטורים לפי סדר הופעתן
  • fct_infreq - המסדר פקטור לפי התפלגות בנתונים
  • fct_lump - מאגד קבוצות נדירות או נפוצות לקבוצת אחר
  • ועוד…
library(forcats)
table(factor(Santander_sample$nomprov))
ALAVA ALBACETE ALICANTE ALMERIA ASTURIAS AVILA BADAJOZ BALEARS, ILLES BARCELONA BIZKAIA BURGOS CACERES CADIZ CANTABRIA CASTELLON CEUTA CIUDAD REAL CORDOBA CORUÑA, A CUENCA GIPUZKOA GIRONA GRANADA GUADALAJARA HUELVA HUESCA JAEN LEON LERIDA LUGO MADRID MALAGA MELILLA MURCIA NAVARRA OURENSE PALENCIA PALMAS, LAS PONTEVEDRA RIOJA, LA SALAMANCA SANTA CRUZ DE SEGOVIA SEVILLA SORIA TARRAGONA TERUEL TOLEDO VALENCIA VALLADOLID ZAMORA ZARAGOZA
277 343 1502 376 1241 156 494 638 5906 1379 437 315 1199 952 436 50 406 583 1313 145 514 313 859 409 386 142 361 479 227 230 33467 1742 70 985 497 250 174 1154 917 369 494 551 203 2874 66 465 52 839 3329 1021 160 1447
table(fct_infreq(Santander_sample$nomprov))
MADRID BARCELONA VALENCIA SEVILLA MALAGA ALICANTE ZARAGOZA BIZKAIA CORUÑA, A ASTURIAS CADIZ PALMAS, LAS VALLADOLID MURCIA CANTABRIA PONTEVEDRA GRANADA TOLEDO BALEARS, ILLES CORDOBA SANTA CRUZ DE GIPUZKOA NAVARRA BADAJOZ SALAMANCA LEON TARRAGONA BURGOS CASTELLON GUADALAJARA CIUDAD REAL HUELVA ALMERIA RIOJA, LA JAEN ALBACETE CACERES GIRONA ALAVA OURENSE LUGO LERIDA SEGOVIA PALENCIA ZAMORA AVILA CUENCA HUESCA MELILLA SORIA TERUEL CEUTA
33467 5906 3329 2874 1742 1502 1447 1379 1313 1241 1199 1154 1021 985 952 917 859 839 638 583 551 514 497 494 494 479 465 437 436 409 406 386 376 369 361 343 315 313 277 250 230 227 203 174 160 156 145 142 70 66 52 50
table(fct_lump(Santander_sample$nomprov, prop = 0.03))
BARCELONA MADRID SEVILLA VALENCIA Other
5906 33467 2874 3329 27618

חבילת haven

אם מייבאים נתונים בעלי פקטורים מ SAS אז חבילת haven שומרת על הפורמטים שלהם ומאפשרת השמת הפורמטים באופן קל בעזרת הפקודה as_factor.

ניתן גם להשתמש בפקודות שלו ישירות בעזרת הפקודה labelled שמצרף למשתנה פקטור.

על מנת ליישם את הפקטור למשתנה יש צורך להריץ אחר כך את הפקודה as_factor.

library(haven)

Santander_sample %>% 
  mutate(ind_nuevo = labelled(ind_nuevo
                              ,c(yes = 1 ,no = 0))) %>%
  mutate(ind_nuevo_grp = as_factor(ind_nuevo)) %>%
  select(ind_nuevo, ind_nuevo_grp) %>% 
  slice(30:35)
ind_nuevo ind_nuevo_grp
0 no
0 no
0 no
0 no
0 no
0 no

חלוקת משתנה לרמות

בעזרת הפקודה factor הפכנו משתנה מקודד למשתנה קטגוריאלי. הפקודה המשלימה עבור משתנה רציף היא פקודה cut החותכת משתנה רציף לקבוצות לפי חחיתוכים נתונים.

הסנטקס המלא:

cut(x, breaks, labels = NULL, include.lowest = FALSE, right = TRUE, dig.lab = 3, ordered_result = FALSE, …)

summary(Santander_sample$renta)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0 52990 95640 120300 153900 28890000
Santander_sample <- Santander_sample %>% 
  mutate( renta_grp = cut(renta
                          ,breaks = c(min(renta), 5290, 95640, max(renta))
                          )
          )

levels(Santander_sample$renta_grp)
## [1] "(0,5.29e+03]"        "(5.29e+03,9.56e+04]" "(9.56e+04,2.89e+07]"
table(Santander_sample$renta_grp)
(0,5.29e+03] (5.29e+03,9.56e+04] (9.56e+04,2.89e+07]
0 24109 36894
table(addNA(Santander_sample$renta_grp))
(0,5.29e+03] (5.29e+03,9.56e+04] (9.56e+04,2.89e+07] NA
0 24109 36894 12785

הפקודה addNA מוסיפה לטבלה ערכים חסרים אם יש


חבילת questionr

חבילת questionr מאפשרת כתיבת קוד אוטומטי ליצירת פקטורים ולחיתוך משתנה רציף לקובוצות בעזרת חלונית עזר נוחה לשימוש.

חשוב לציין שחלונית העזר רק מכינה לנו את הקוד להרצה ולא מבצעת אותו עבורינו…


שינוי סוג נתונים

לפעמים נרצה לשנות את סוג המשתנה מסוג אחד למשנהו. רוב הפקודות לשנות סוג משתנה למשתנה אחר הם בעלי הסנטקס as.Something .

למשל:

  • as.data.frame(x) - to coerce x to a data.frame
  • as.numeric(x) - to coerce x to numeric
  • as.character(x) - to coerce x to character
  • as.date(x) - to coerce x to date
  • ועוד

כמובן שניתן להשתמש בסינטקס הזה בתוך פקודת mutate של חבילת dplyr.


תאריכים

ב R תאריכים נשמרים כסוג מיוחד של פקטור הנקרא POSTIxt או POSTIc.

יש הרבה אפשרויות לעיבוד תאריכים. אנו נשתמש בספריית lubridate שגם היא חלק מה tidyverse.

קודם נטעין את הספריה.

library(lubridate)

הגדרת משתנה כתאריך

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

עם ספרית lubridate אנו משתמשים בפקודה מסוג dmy כאשר שם הפקודה משתנה בהתאם לפורמט התאריך

המשמעות של כל אות מובנת:

  • d - day
  • m - month
  • y - year
  • h - hour
  • m - minute
  • s - second

למשל עבור תאריך שקודד כיום, חודש, שנה נפעיל את הפקודה:

dmy(variable)

אם התאריך קודד כשנה יום חודש נכתוב:

ydm(variable)

ואם זה timestamp אז נכתוב:

dmy_hms()

אחרי שמכילים את הפקודה הנתון נשמר כתאריך

ymd(20070828)
## [1] "2007-08-28"
ymd("2007/08/28")
## [1] "2007-08-28"
ymd("2007Aug28")
## [1] "2007-08-28"
dmy("28-08-2007")
## [1] "2007-08-28"
start_date <- Santander_sample$fecha_dato

str(start_date)
##  POSIXct[1:73788], format: "2015-04-28" "2016-01-28" "2016-01-28" "2016-03-28" ...

שליפת חלקי תאריך

על מנת להוציא חלקים ספיצפיים מתאריך נשתמש בפקודות:

  • day
  • month
  • year
  • hour
  • minute
  • second
start_date[1]
## [1] "2015-04-28 UTC"
day(start_date[1])
## [1] 28
month(start_date[1])
## [1] 4
year(start_date[1])
## [1] 2015
hour(start_date[1])
## [1] 0
minute(start_date[1])
## [1] 0
second(start_date[1])
## [1] 0

קידום ופיגור תאריכים

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

  • פיגור תקופה %m-%
  • קידום תקופה %m+%

בשילוב עם רכיב התאריך שאנו רוצים לקדם וכמות היחידות שרוצים לקדם בעזרת הפונקציות הבאות

  • ימים days
  • חודשים months
  • שנים years
start_date[1]
## [1] "2015-04-28 UTC"
start_date[1]  %m+% days(5)
## [1] "2015-05-03 UTC"
start_date[1]  %m-% months(2)
## [1] "2015-02-28 UTC"
start_date[1]  %m+% years(3)
## [1] "2018-04-28 UTC"
end_date <- start_date[1]  %m+% years(3) %m-% months(2)
end_date
## [1] "2018-02-28 UTC"

חשבון עם תאריכים

הדרך היעילה ביותר לחשב הפרש בין תאריכים הוא להגדיר זוג תאריכים כ interval , שהוא סוג חדש של משתנה שמוגדר לפי זמן התחלה וזמן סיום.

t <- interval(start_date[1], end_date)

t
## [1] 2015-04-28 UTC--2018-02-28 UTC

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

אחרי שמגדירים את ה interval אפשר “לחלק” את ה interval ביחידות שאנו רוצים על מנת לקבל את ערך הזמן הרצוי.

בעזרת האופרטור %/% ולאחריו סוג ומספר התקופות שאנו רוצים:

t%/%days(1)
## [1] 1037
t%/%months(1)
## [1] 34
t%/%years(1)
## [1] 2

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

end_date <- start_date[1] %m+% days(32)
end_date
## [1] "2015-05-30 UTC"
difference <- end_date - start_date[1]
difference
## Time difference of 32 days
as.period(difference, unit='m')
## [1] "32d 0H 0M 0S"