בשיעורים הקודמים למדנו את הבסיס של R.
מעכשיו עד סוף הקורס אנו נשתמש בספריות חיצוניות שעושות את העבודה ב R להרבה יותר קלה ומוסיפות פונקציונאליות רבה לתוכנה.
בשיעור הזה נתרכז במספר ספריות המהוות חלק מאוסף של ספריות המאוגדות תחת הכותרת ה tidyverse
.
הספריות שנתמקד בהן בשיעור הזה הן:
dplyr
- שפה נוחה לשאילתות
tidyr
- פקודות לביצוע מנפולציות על טבלאות
reshape2
- פקודות לשחלוף מבנה אובייקטים
ספריה חיצונית היא סוג של תוספת פקודות שמישהו כתב והנגיש לציבור הרחב.
כדי להשתמש בספריה אנחנו צריכים להוריד אותה מהאינטרנט כאשר רוב הספריות של R נשמרות במאגר נגיש לציבור באתר CRAN
לרוב, מציאת הספריה המתאימה הוא עניין של חיפוש חופשי באינטרנט, כאשר באתר של CRAN מוצע רשימת נושאים בשם task view, המכילה סקירה של החבילות העדכניות באותו נושא:
https://cran.r-project.org/web/views
מ RSTUDIO אפשר לחפש ולהוריד ספריות לפי שם מטאב Packages וללחוץ על הכפתור Install
הספריות נשמרות בתיקיה במחשב שהוגדר מראש, שם R יודע לחפש אותם.
הערה: אם רוצים להעתיק חבילה מסוימת ממחשב אחד למחשב אחר, זה לא מספיק רק להעתיק את הספריה הרצויה, כיוון שהרבה ספריות בנויות על ספריות אחרות ולכן יש לוודא שכל הספריות שאותה ספריה תלויה בהן, נמצאים
את רשימת הספריות האחרות שהספריה תלויה בהן ניתן לראות בקובץ ה DESCRIPTION של הספריה תחת הכותרת Imports.
tidyverse
לפני כל פעם שרוצים להשתמש באחד הפקודות השייכים לספריה, צריך להטעין אותה לתוך הזכרון בעזרת הפקודה library
כך:
# Install readr package:
library(readr)
לחלופין ניתן לסמן אותה ב V ב טאב של ה Packages
עכשיו כל הפקודות של הספריה זמינות לשימוש
בכתיבת script רצוי לייבא את כל הספריות הנחוצות בתחילת ה script.
כיוון שהספריות של R נכתבים בצורה פתוחה לציבור, קורא לפעמים שספריות משתמשות באותן שמות של פקודות. במקרים כאלה R יתייחס לפקודה שבאה מהספריה האחרונה שהותקנה.
יש שתי דרכים לטפל בבעיה הזאת:
detach
או על ידי הורדת ה V ליד שם הרשימה בטאב של ה Packages::
ושם הפקודה.הפתרון השני אפילו אין צורך להטעין את החבילה לזכרון.
לדוגמא, אם נרצה לקרוא לפקודה select
מתוך החבילה dplyr
נוכל לכתוב:
dplyr::select(table, column)
כל הפקודות של הספריה מתועדות עם עזרה שניתן לראות בדרך הרגילה (שימוש בחלונית החיפוש או ב ?)
בנוסף, בחבילות רבות יש תעוד כללי עם דוגמאות והסבר ידידותי למשתמש שנקרא Vigenette
כדי לראות אותה:
dplyr
בעבר הלא רחוק, הייתם צריכים לכתוב קוד בשביל לייבא נתונים ממקורות חיצוניים.
כיום, יש אפשרות נוחה לייבא נתונים בעזרת לחיצה על הכפתור Import Dataset
ובחירת סוג הנתונים הרצוי.
בעזרת ספריות חיצוניות ניתן לחבר את R למאגרי נתונים כגון SQL, ORACLE , ועוד רבים אחרים. נלמד איך לעשות את זה בשיערוים הבאים.
ב R הנתונים נשמרים בתור סביבת עבודה הנקרא workspace, ונשמר כקובץ עם סיומת *.RData אותו ניתן להטעין ולשמור בעזרת האיקונים ב RSTUDIO. או בעזרת הפקודות load
- לקריאת קובץ שמור; ו save
לשמירת סביבת העבודה.
בפתיחת קובץ ה CSV, שימו לב לכמה דברים:
חבילת ה tidyverse מאגדת בתוכה מספר חבילות שמייצרות שפה חדשה לטיפול בנתונים ב R.
המשותף לכל הספריות הכללות ב tidyverse הוא המיקוד בניקוי , סידור וביצוע פעולות על טבלאות. כאשר הפילוסופיה של טבלה “מסודרת” היא ש:
בין החבילות הבולטות שנעשה בהן שימוש:
למעשה, אלה החבילות הנפוצות ביותר וניתן להטעין אותן בהטענת החבילה tidyverse
נגע בקצרה או נשתמש בעקיפין במספר ספריות נוספות:
לרשימה המלאה של הספריות הכללולות ראו בלינק:
https://github.com/tidyverse/tidyverse
ברוב הפקודות של ה tidyverse
ה syntax הוא בצורת:
functionName(tableName, paramters)
למשל:
summarise(Table, mean(Variable1))
select(Table, col1, col2, col3)
group_by(Table, group1)
אבל כשמתשמשים בכמה פקודות יחד זה נהיה מסורבל
אם נרצה ממוצע של המשתנה אושר לפי ענף, נכתוב:
library(dplyr)
grp_seg <- group_by(Santander_sample, segmento)
sum_table <- summarise(grp_seg, mean(renta))
#print results
sum_table %>% slice(1:10)
## Warning: package 'bindrcpp' was built under R version 3.3.3
segmento | mean(renta) |
---|---|
01 - TOP | 146564.34 |
02 - PARTICULARES | 117166.78 |
03 - UNIVERSITARIO | 92802.54 |
אופציה נוספת הייתה לשים את זה ישר בפנים ככה:
sum_table <- summarise(group_by(Santander_sample,segmento), mean(renta))
#print results
sum_table %>% slice(1:10)
segmento | mean(renta) |
---|---|
01 - TOP | 146564.34 |
02 - PARTICULARES | 117166.78 |
03 - UNIVERSITARIO | 92802.54 |
אבל שני האופציות יוצרות סיבוכיות:
לכן המציאו פתרון האופרטור %>%
%>%
האופרטור %>%
אומר: " שים את מה שמשמאל בתור המשתנה הראשון בפונקציה שמימין"
הפקודות נכתבות בסדר שנרצה לבצע אותם!!
כפי שתראו זה יוצר קוד נקי מובן ומונע את הבעיות דלעיל.
עכשיו נכתוב:
sum_table <- Santander_sample %>%
group_by(segmento) %>%
summarize(mean(renta))
#print results
sum_table %>% slice(1:10)
segmento | mean(renta) |
---|---|
01 - TOP | 146564.34 |
02 - PARTICULARES | 117166.78 |
03 - UNIVERSITARIO | 92802.54 |
ניתן להשתמש באופרטור בכל הפקודות לא רק של dplyr
מעכשיו נשתדל להשתמש באופרטור הזה בכל שאילתה מורכבת.
הקיצור לאופרטור הוא Ctrl Shift M
.
לפעמים נרצה להשתמש באופרטור %>%
שלא בתור הערך של הפרמטר הראשון בפקודה
במקרים כאלה , ובאופן כללי כשאנחנו רוצים לסמן השמה במקום מסוים, נשתמש בסימון .
כדי לשמור את המקום עבור הפרמטר/ משתנה
כפי שצויין קודם, הטבלה שייבאנו לתוך ה workspace נשמרה בתור tbl_df
שזה השם קיצור ל tibble.
tibble היא סוג של data frame משודרג השייכת ל tidyverse
שההבדלים ביניהם הן:
שימו לב שהטבלה עדיין תהיה data frame ונוכל לבצע את כל מה שלמדנו בשיעור הקודם גם בטבלאות מסוג tibble
אם היינו רוצים להפוך טבלה ל tibble היינו יכולים לכתוב:
Santander_sample <- tbl_df(Santander_sample)
# show table properties
class(Santander_sample)
## [1] "tbl_df" "tbl" "data.frame"
dplyr
ספרית dplyr
תהיה סוס העבודה שלנו להמשך הקורס
הפקודות בה מאשפרות:
הפילוסופיה של הספריה היא שכל פקודה תעשה משהו אחד בלבד - בצורה הטובה ביותר
בהתאם לכך, רוב הזמן נשתמש במספר פקודות ביחד כדי לבצע משימה
הפקודות הבסיסיות הן:
filter
- סינון נתונים לפי תנאיםarrange
- מיון נתונים לפי שדותselect
- בחירת שדות מסוימותgroup_by
- קיבוץ לפי קבוצותsummarise
- סיכום עמודה לערך אחדmutate
- שינוי שדה ויצירת שדה חדשrename
- שינוי שם שדהdistinct
- בחירת שורות ייחודיותtransmutate
- החזרת רק שדה מחושבslice
- בחירת שורות לפי מיקום , למשל 10 הראשונים
mutate_at
- בצע שינוי או חישוב על כל עמודה מסומנתsummarise_at
- בצע סיכום לכל עמודה מסומנתmutate_all
- בצע שינוי או חישוב על כל העמודותsummarise_all
- בצע סיכום לכל העמודותmutate_if
- בצע שינוי או חישוב על כל עמודה העומדת בתנאיsummarise_if
- בצע סיכום לכל עמודה העומדת בתנאי
n_distinct
- מחזיר מספר שורות ייחודיותcount
- טבלת שכיחותtally
- ספירה או סכימת עמודה
כפי שאתם רואים יש הרבה פקודות (ואלה רק השימושיות ביותר)
בהמשך נעבור על עוד משפחה של פקודות שיעזרו לחבר נתונים
בנוסף אתם מוזמנים להשתמש ב cheat-sheet המצורף בכל עת.
לפני שנלך ונסתבך, בואו נראה טבלת שכיחויות בסיסית: לפי סגמנט
sum_tbl <- Santander_sample %>%
count(segmento)
# print results
sum_tbl %>% slice(1:10)
segmento | n |
---|---|
01 - TOP | 7934 |
02 - PARTICULARES | 65854 |
03 - UNIVERSITARIO | 26212 |
sum_tbl <- Santander_sample %>%
count(fecha_dato, segmento)
# print results
sum_tbl %>% slice(1:10)
fecha_dato | segmento | n |
---|---|---|
2015-04-28 | 01 - TOP | 1569 |
2015-04-28 | 02 - PARTICULARES | 12448 |
2015-04-28 | 03 - UNIVERSITARIO | 4507 |
2015-07-28 | 01 - TOP | 1479 |
2015-07-28 | 02 - PARTICULARES | 12614 |
2015-07-28 | 03 - UNIVERSITARIO | 4510 |
2015-10-28 | 01 - TOP | 1547 |
2015-10-28 | 02 - PARTICULARES | 13316 |
2015-10-28 | 03 - UNIVERSITARIO | 5361 |
2016-01-28 | 01 - TOP | 1616 |
זה די אינטואטיבי - נבחר רק את השדות: סגמנט ואינדיקטור לכרטיס אשראי (ind_cc) ותאריך
segment_cc <- Santander_sample %>%
select(segmento
, ind_cc
, fecha_dato
, age
, sexo)
segment_cc %>% slice(1:10)
segmento | ind_cc | fecha_dato | age | sexo |
---|---|---|---|---|
01 - TOP | 0 | 2015-04-28 | 92 | H |
02 - PARTICULARES | 0 | 2016-01-28 | 49 | V |
03 - UNIVERSITARIO | 0 | 2016-01-28 | 20 | V |
02 - PARTICULARES | 0 | 2016-01-28 | 53 | V |
02 - PARTICULARES | 0 | 2016-03-28 | 48 | H |
02 - PARTICULARES | 0 | 2016-01-28 | 72 | V |
02 - PARTICULARES | 0 | 2015-04-28 | 49 | V |
02 - PARTICULARES | 0 | 2015-07-28 | 53 | V |
01 - TOP | 0 | 2016-01-28 | 67 | V |
02 - PARTICULARES | 0 | 2015-10-28 | 54 | V |
select
, למשל:segment_cc <- Santander_sample %>%
select(segmento
, ind_cc
, fecha_dato
, age
, sex = sexo)
segment_cc %>% slice(1:10)
segmento | ind_cc | fecha_dato | age | sex |
---|---|---|---|---|
01 - TOP | 0 | 2015-04-28 | 92 | H |
02 - PARTICULARES | 0 | 2016-01-28 | 49 | V |
03 - UNIVERSITARIO | 0 | 2016-01-28 | 20 | V |
02 - PARTICULARES | 0 | 2016-01-28 | 53 | V |
02 - PARTICULARES | 0 | 2016-03-28 | 48 | H |
02 - PARTICULARES | 0 | 2016-01-28 | 72 | V |
02 - PARTICULARES | 0 | 2015-04-28 | 49 | V |
02 - PARTICULARES | 0 | 2015-07-28 | 53 | V |
01 - TOP | 0 | 2016-01-28 | 67 | V |
02 - PARTICULARES | 0 | 2015-10-28 | 54 | V |
rename
באותה צורה, כאשר בניגוד ל rename
,select
מחזיר את כל שאר העמודות()everything
המסמן את כל שאר העמודות :segment_cc <- segment_cc %>%
select(sex, age, everything())
segment_cc %>% slice(1:10)
sex | age | segmento | ind_cc | fecha_dato |
---|---|---|---|---|
H | 92 | 01 - TOP | 0 | 2015-04-28 |
V | 49 | 02 - PARTICULARES | 0 | 2016-01-28 |
V | 20 | 03 - UNIVERSITARIO | 0 | 2016-01-28 |
V | 53 | 02 - PARTICULARES | 0 | 2016-01-28 |
H | 48 | 02 - PARTICULARES | 0 | 2016-03-28 |
V | 72 | 02 - PARTICULARES | 0 | 2016-01-28 |
V | 49 | 02 - PARTICULARES | 0 | 2015-04-28 |
V | 53 | 02 - PARTICULARES | 0 | 2015-07-28 |
V | 67 | 01 - TOP | 0 | 2016-01-28 |
V | 54 | 02 - PARTICULARES | 0 | 2015-10-28 |
ועכשיו נמיין את הקובץ החדש לפי שתי השדות:
segment_cc <- segment_cc %>%
arrange(segmento, ind_cc)
#print results
segment_cc %>% slice(1:10)
sex | age | segmento | ind_cc | fecha_dato |
---|---|---|---|---|
H | 92 | 01 - TOP | 0 | 2015-04-28 |
V | 67 | 01 - TOP | 0 | 2016-01-28 |
V | 55 | 01 - TOP | 0 | 2015-07-28 |
V | 50 | 01 - TOP | 0 | 2015-07-28 |
V | 62 | 01 - TOP | 0 | 2015-04-28 |
V | 75 | 01 - TOP | 0 | 2015-10-28 |
V | 68 | 01 - TOP | 0 | 2015-10-28 |
V | 35 | 01 - TOP | 0 | 2015-04-28 |
V | 74 | 01 - TOP | 0 | 2016-03-28 |
V | 47 | 01 - TOP | 0 | 2015-10-28 |
ואם נרצה לסדר חלק מהמשתנים בסדר יורד נשים אותם ב desc()
segment_cc <- segment_cc %>%
arrange(segmento, fecha_dato, desc(ind_cc))
# print results
segment_cc %>% slice(1:10)
sex | age | segmento | ind_cc | fecha_dato |
---|---|---|---|---|
V | 63 | 01 - TOP | 1 | 2015-04-28 |
V | 48 | 01 - TOP | 1 | 2015-04-28 |
V | 53 | 01 - TOP | 1 | 2015-04-28 |
V | 63 | 01 - TOP | 1 | 2015-04-28 |
V | 40 | 01 - TOP | 1 | 2015-04-28 |
V | 52 | 01 - TOP | 1 | 2015-04-28 |
V | 58 | 01 - TOP | 1 | 2015-04-28 |
V | 36 | 01 - TOP | 1 | 2015-04-28 |
V | 40 | 01 - TOP | 1 | 2015-04-28 |
V | 42 | 01 - TOP | 1 | 2015-04-28 |
עכשיו נראה את 5 השורות עם האושר הכי נמוך
segment_bottom_5 <- Santander_sample %>%
select(renta, fecha_dato, segmento, ind_cc) %>%
arrange(renta) %>%
slice(1:5)
#print results
segment_bottom_5 %>% slice(1:5)
renta | fecha_dato | segmento | ind_cc |
---|---|---|---|
0 | 2016-03-28 | 02 - PARTICULARES | 0 |
0 | 2015-07-28 | 02 - PARTICULARES | 0 |
0 | 2015-10-28 | 02 - PARTICULARES | 0 |
0 | 2015-07-28 | 03 - UNIVERSITARIO | 0 |
0 | 2015-07-28 | 02 - PARTICULARES | 0 |
:
כדי לציין את המספרים 1 עד 5עכשיו נסנן ונראה את האושר הכי נמוך מעל 100:
# After Filter
segment_bottom_5 <- Santander_sample %>%
select(renta, fecha_dato, segmento, ind_cc) %>%
filter(renta>100) %>%
arrange(renta) %>%
slice(1:5)
#print results
segment_bottom_5
renta | fecha_dato | segmento | ind_cc |
---|---|---|---|
7376.79 | 2015-07-28 | 02 - PARTICULARES | 0 |
7376.79 | 2015-10-28 | 02 - PARTICULARES | 0 |
7507.32 | 2015-04-28 | 01 - TOP | 0 |
7816.92 | 2016-01-28 | 03 - UNIVERSITARIO | 0 |
8552.88 | 2015-04-28 | 03 - UNIVERSITARIO | 0 |
שימו לב: את הסינון תשימו לפי סדר הפעולות שאתם רוצים לבצע
בעזרת הפקודה הזו ניתן לחשב סיכומים שונים לאיזה עמודות שנרצה
# sum of amala, number of observations
sum_tbl <- summarise(Santander_sample
,Total= sum(renta)
,"Min"= min(renta)
,"Max"= max(renta)
,"Median"= median(renta)
,"Mean"= mean(renta)
,"Standard deviation"= sd(renta)
,"Freq"= n()
)
#Print Results
sum_tbl
Total | Min | Max | Median | Mean | Standard deviation | Freq |
---|---|---|---|---|---|---|
11311283030 | 0 | 28894396 | 89517.77 | 113112.8 | 248050.3 | 1e+05 |
הפקודה לא עושה שום דבר בפני עצמה.
אבל היא עושה הרבה מאוד בשילוב עם שאר הפקודות
עכשיו בוא ננסה לראות את אותו דבר לפי סגמנט בעזרת group_by
sum_tbl <- Santander_sample %>%
group_by(segmento) %>%
summarise("Total"=sum(renta)
,"Min"=min(renta)
,"Max"=max(renta)
,"Median"=median(renta)
,"Mean"=mean(renta)
,"Standard deviation"=sd(renta)
,"Freq"=n()
)
#Print Results
sum_tbl
segmento | Total | Min | Max | Median | Mean | Standard deviation | Freq |
---|---|---|---|---|---|---|---|
01 - TOP | 1162841489 | 0 | 11139896 | 121900.53 | 146564.34 | 236408.3 | 7934 |
02 - PARTICULARES | 7715901289 | 0 | 28894396 | 93111.86 | 117166.78 | 255736.2 | 65854 |
03 - UNIVERSITARIO | 2432540252 | 0 | 28894396 | 74792.31 | 92802.54 | 229607.9 | 26212 |
הערה חשובה: בטבלה שיצרתםם בעזרת group_by
היא תמיד תהיה מקובצת תחת הקבוצה שיצרתם
על מנת להסיר את הקיבוץ תפעילו את הפקודה ungroup()
בא נגיד שאנו רוצים לחשב עמודה נוספת המבטא את הותק בשנים (במקום בחודשים)
calc_vetek <- Santander_sample %>%
mutate(vetek_yrs = antiguedad/12 ) %>%
select(antiguedad, vetek_yrs, age, segmento)
#print results
calc_vetek %>% slice(1:10)
antiguedad | vetek_yrs | age | segmento |
---|---|---|---|
218 | 18.1666667 | 92 | 01 - TOP |
116 | 9.6666667 | 49 | 02 - PARTICULARES |
4 | 0.3333333 | 20 | 03 - UNIVERSITARIO |
115 | 9.5833333 | 53 | 02 - PARTICULARES |
33 | 2.7500000 | 48 | 02 - PARTICULARES |
105 | 8.7500000 | 72 | 02 - PARTICULARES |
142 | 11.8333333 | 49 | 02 - PARTICULARES |
114 | 9.5000000 | 53 | 02 - PARTICULARES |
20 | 1.6666667 | 67 | 01 - TOP |
197 | 16.4166667 | 54 | 02 - PARTICULARES |
מה שלא מובן מאליו הוא שאפשר להשתמש בשדה החדש עוד באותו פקודה!
למשל, אם בנוסף הייתי רוצה עוד עמודה המחשבת באיזה גיל התחיל כלקוח
calc_vetek <- Santander_sample %>%
mutate( vetek_yrs = antiguedad/12
,age_lakoach_start = age - vetek_yrs ) %>%
select(antiguedad, vetek_yrs, age, age_lakoach_start, segmento)
calc_vetek %>% slice(1:10)
antiguedad | vetek_yrs | age | age_lakoach_start | segmento |
---|---|---|---|---|
218 | 18.1666667 | 92 | 73.83333 | 01 - TOP |
116 | 9.6666667 | 49 | 39.33333 | 02 - PARTICULARES |
4 | 0.3333333 | 20 | 19.66667 | 03 - UNIVERSITARIO |
115 | 9.5833333 | 53 | 43.41667 | 02 - PARTICULARES |
33 | 2.7500000 | 48 | 45.25000 | 02 - PARTICULARES |
105 | 8.7500000 | 72 | 63.25000 | 02 - PARTICULARES |
142 | 11.8333333 | 49 | 37.16667 | 02 - PARTICULARES |
114 | 9.5000000 | 53 | 43.50000 | 02 - PARTICULARES |
20 | 1.6666667 | 67 | 65.33333 | 01 - TOP |
197 | 16.4166667 | 54 | 37.58333 | 02 - PARTICULARES |
לפעמים זה יהיה שימושי להחזיר רק את החישוב:
calc_vetek <- Santander_sample %>%
transmute( vetek_yrs = antiguedad/12
,age_lakoach_start = age - vetek_yrs )
# print results
calc_vetek %>% slice(1:10)
vetek_yrs | age_lakoach_start |
---|---|
18.1666667 | 73.83333 |
9.6666667 | 39.33333 |
0.3333333 | 19.66667 |
9.5833333 | 43.41667 |
2.7500000 | 45.25000 |
8.7500000 | 63.25000 |
11.8333333 | 37.16667 |
9.5000000 | 43.50000 |
1.6666667 | 65.33333 |
16.4166667 | 37.58333 |
לפונקציות summarise
ו transform
יש גרסאות שונות לביצוע אותו פעולה על מספר עמודות:
עבור פקודת mutate
יש :
mutate_at
- בצע שינוי או חישוב על כל עמודה מסומנתmutate_all
- בצע שינוי או חישוב על כל העמודותmutate_if
- בצע שינוי או חישוב על כל עמודה העומדת בתנאי
עבור פקודת summarise
יש :
summarise_all
- בצע סיכום לכל העמודותsummarise_at
- בצע סיכום לכל עמודה מסומנתsummarise_if
- בצע סיכום לכל עמודה העומדת בתנאי
אנו נדגים אחד מכל סוג - להרחבה ראו עזרה על summarise_all
אם יש פקודה שרוצים לבצע לכמה עמודות, במקום לכתוב כל אחד בנפרד אפשר להשתמש ב mutate_each.
ה syntax של הפקודה היא:
mutate_at(.tbl, .cols, .funs, …)
כאשר :
()vars
()funs
למשל, לעגל את העמודות המחושבות
calc_vetek2 <- calc_vetek %>%
mutate_at(vars(vetek_yrs, age_lakoach_start)
, funs(round))
# print result
calc_vetek2 %>% slice(1:10)
vetek_yrs | age_lakoach_start |
---|---|
18 | 74 |
10 | 39 |
0 | 20 |
10 | 43 |
3 | 45 |
9 | 63 |
12 | 37 |
10 | 44 |
2 | 65 |
16 | 38 |
# If we want the original values we need to add names!!!
calc_vetek2 <- calc_vetek %>%
mutate_at(vars(vetek_yrs, age_lakoach_start)
, funs("new" = round))
# print result
calc_vetek2 %>% slice(1:10)
vetek_yrs | age_lakoach_start | vetek_yrs_new | age_lakoach_start_new |
---|---|---|---|
18.1666667 | 73.83333 | 18 | 74 |
9.6666667 | 39.33333 | 10 | 39 |
0.3333333 | 19.66667 | 0 | 20 |
9.5833333 | 43.41667 | 10 | 43 |
2.7500000 | 45.25000 | 3 | 45 |
8.7500000 | 63.25000 | 9 | 63 |
11.8333333 | 37.16667 | 12 | 37 |
9.5000000 | 43.50000 | 10 | 44 |
1.6666667 | 65.33333 | 2 | 65 |
16.4166667 | 37.58333 | 16 | 38 |
# to pass arithematic transfomration use `.` instead of the coloumn name
calc_vetek2 <- calc_vetek %>%
mutate_at(vars(vetek_yrs, age_lakoach_start)
,funs("mnths" = .*12) )
# print result
calc_vetek2 %>% slice(1:10)
vetek_yrs | age_lakoach_start | vetek_yrs_mnths | age_lakoach_start_mnths |
---|---|---|---|
18.1666667 | 73.83333 | 218 | 886 |
9.6666667 | 39.33333 | 116 | 472 |
0.3333333 | 19.66667 | 4 | 236 |
9.5833333 | 43.41667 | 115 | 521 |
2.7500000 | 45.25000 | 33 | 543 |
8.7500000 | 63.25000 | 105 | 759 |
11.8333333 | 37.16667 | 142 | 446 |
9.5000000 | 43.50000 | 114 | 522 |
1.6666667 | 65.33333 | 20 | 784 |
16.4166667 | 37.58333 | 197 | 451 |
ובצורה דומה , אם נרצה סיכום של מספר עמודות נשתמש ב summarise_each.
ה syntax הוא:
summarise_all(.tbl, .funs, …)
כאשר :
()funs
למשל ערך אחוזון 5 וממוצע:
sum_tbl <- calc_vetek %>%
summarise_all( funs("p5" = quantile(.,0.05) , mean) )
#print results
sum_tbl
vetek_yrs_p5 | age_lakoach_start_p5 | vetek_yrs_mean | age_lakoach_start_mean |
---|---|---|---|
0.4166667 | 19.33333 | 6.97477 | 35.03157 |
.
במקום השם של המשתנה שמשתמשים בואפשר לחשב פונקציות אגרגטיביות (כמו ממוצע מקסימום ומינימום) ולחבר את התוצאה ישר לטבלה בשילוב עם mutate.
בנוסף אפשר להשתמש בהם גם עם filter כדי לסנן תוך כדי בלי לייצר משתנה חדש.
רק להדגים חלק מהפקודות:
# Show Percent and cumulative Percent
renta_stats <- Santander_sample %>%
select(renta) %>%
arrange(desc(renta)) %>%
mutate(sum_renta = sum(renta)
,mean_renta = mean(renta)
,min_renta = min(renta)
,max_renta = max(renta)
,meidan_renta = median(renta)
,sd_renta = sd(renta)
,lag_renta = lag(renta)
,lead_renta = lead(renta)
,cum_sum_renta = cumsum(renta)
,cum_mean_renta = cummean(renta)
,cum_min_renta = cummin(renta)
,cum_max_renta = cummax(renta)
,rank_renta = row_number(renta)
,rank2_renta = min_rank(renta)
,rank3_renta = dense_rank(renta)
,rank4_renta = percent_rank(renta)
,ntile_renta = ntile(renta, 3)
,cum_dist = cume_dist(renta)
)
renta_stats %>% slice(1:10)
renta | sum_renta | mean_renta | min_renta | max_renta | meidan_renta | sd_renta | lag_renta | lead_renta | cum_sum_renta | cum_mean_renta | cum_min_renta | cum_max_renta | rank_renta | rank2_renta | rank3_renta | rank4_renta | ntile_renta | cum_dist |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
28894396 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | NA | 28894396 | 28894396 | 28894396 | 28894396 | 28894396 | 99999 | 99999 | 67773 | 0.99999 | 3 | 1.00000 |
28894396 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 28894396 | 22034738 | 57788792 | 28894396 | 28894396 | 28894396 | 100000 | 99999 | 67773 | 0.99999 | 3 | 1.00000 |
22034738 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 28894396 | 22034738 | 79823530 | 26607843 | 22034738 | 28894396 | 99997 | 99997 | 67772 | 0.99997 | 3 | 0.99998 |
22034738 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 22034738 | 15711716 | 101858268 | 25464567 | 22034738 | 28894396 | 99998 | 99997 | 67772 | 0.99997 | 3 | 0.99998 |
15711716 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 22034738 | 13268621 | 117569984 | 23513997 | 15711716 | 28894396 | 99996 | 99996 | 67771 | 0.99996 | 3 | 0.99996 |
13268621 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 15711716 | 11411517 | 130838605 | 21806434 | 13268621 | 28894396 | 99995 | 99995 | 67770 | 0.99995 | 3 | 0.99995 |
11411517 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 13268621 | 11202220 | 142250122 | 20321446 | 11411517 | 28894396 | 99994 | 99994 | 67769 | 0.99994 | 3 | 0.99994 |
11202220 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 11411517 | 11139896 | 153452342 | 19181543 | 11202220 | 28894396 | 99993 | 99993 | 67768 | 0.99993 | 3 | 0.99993 |
11139896 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 11202220 | 9833873 | 164592238 | 18288026 | 11139896 | 28894396 | 99992 | 99992 | 67767 | 0.99992 | 3 | 0.99992 |
9833873 | 11311283030 | 113112.8 | 0 | 28894396 | 89517.77 | 248050.3 | 11139896 | 9792857 | 174426111 | 17442611 | 9833873 | 28894396 | 99991 | 99991 | 67766 | 0.99991 | 3 | 0.99991 |
sum_tbl <- Santander_sample %>%
filter( renta == max(renta))
sum_tbl2 <- Santander_sample %>%
filter( renta > mean(renta))
sum_tbl2 <- Santander_sample %>%
filter( renta > median(renta))
sum_tbl2 %>% select(renta, segmento) %>% slice(1:10)
renta | segmento |
---|---|
249323.8 | 02 - PARTICULARES |
171329.0 | 03 - UNIVERSITARIO |
108166.5 | 02 - PARTICULARES |
169832.1 | 02 - PARTICULARES |
130283.7 | 02 - PARTICULARES |
172876.4 | 02 - PARTICULARES |
271485.1 | 02 - PARTICULARES |
109185.4 | 01 - TOP |
128760.4 | 02 - PARTICULARES |
121056.3 | 03 - UNIVERSITARIO |
duplicates
- מציאת כפילויותיש מספר דרכים לזהות שורות לא ייחודיות:
נגדים רק על חלק מהשיטות
בואו נשווה בין מספר שורות ייחודיות n_distinct לבין מספר שורות סך הכל n, בפקודת summarise
summarise(Santander_sample
, "N Distinct" = n_distinct(segmento)
, "N" = n())
N Distinct | N |
---|---|
3 | 1e+05 |
עכשיו נקח רק שורות ייחודיות לפי המשתנה segmento בעזרת distinct
seg_distinct <- Santander_sample %>%
distinct(segmento, .keep_all = TRUE)
seg_distinct[,1:5]
fecha_dato | ncodpers | ind_empleado | pais_residencia | sexo |
---|---|---|---|---|
2015-04-28 | 64154 | N | ES | H |
2016-01-28 | 616876 | N | ES | V |
2016-01-28 | 1448463 | N | ES | V |
ונסתכל על השורות הכפולות בעזרת סינון שורות שמופיעות מספר פעמים:
dups <- Santander_sample %>%
group_by(segmento) %>%
filter(row_number()>1)
dups %>% select(1:5) %>% slice(1:3)
## Adding missing grouping variables: `segmento`
## # A tibble: 9 x 6
## # Groups: segmento [3]
## segmento fecha_dato ncodpers ind_empleado pais_residencia
## <chr> <dttm> <int> <chr> <chr>
## 1 01 - TOP 2016-01-28 1258317 N ES
## 2 01 - TOP 2015-10-28 691001 N ES
## 3 01 - TOP 2015-07-28 217566 N ES
## 4 02 - PARTICULARES 2016-01-28 621277 N ES
## 5 02 - PARTICULARES 2016-03-28 1137501 N ES
## 6 02 - PARTICULARES 2016-01-28 685293 N ES
## 7 03 - UNIVERSITARIO 2016-01-28 1277143 N ES
## 8 03 - UNIVERSITARIO 2016-03-28 985359 N ES
## 9 03 - UNIVERSITARIO 2015-07-28 658233 N ES
## # ... with 1 more variables: sexo <chr>
עכשיו יש לכם את הכלים לבצע כמעט כל אנליזה שתרצו על הנתונים שלכם!
TableName %>%
group_by(groupVariables) %>%
select(selectedColumns) %>%
mutate(calculatedColumns)
filter(filterConditions) %>%
arrange(orderByVariables)
ואם אתם מבצעים סיכום משתנה זה בדרך כלל משהו כזה:
TableName %>%
group_by(groupVariables) %>%
summarise(summaryStatistics)
כמובן שהכל לפי הצורך! ולא חייב להראות ככה בכלל !!!!
עכשיו תורכם!!!
קבוצה אחרת של פונקציות שרצוי שנכיר הן פונקציות המקשרות בין טבלאות
רוב המשפחה של פונקציות אלה נגמרים בסיומת _join :
מי שמכיר SQL ירגיש בבית.
אנו נעבור רק על left_join השאר באותו שיטה
למי שלא מכיר, הפקודה מחברת לטבלה הראשונה את כל הרשומות המופיעות בטבלה השנייה שיש להם שדה מפתח זהה.
ה syntax הבסיסי:
עבור שדה בעל אותו שם בשני הטבלאות:
new_table <- left_join(table1, table2, by=“keyValue”)
אם המפתח בעל שם שונה בשני הטלאות:
new_table <- left_join(table1, table2, by=c(“key1”=“key2”))
אם החיבור נעשה על ידי מספר שדות זה יצויין כך:
new_table <- left_join(table1, table2 ,by=c(“table1key1”=“table2key1” ,“table1key2”=“table2key2” ))
זה אמור לכסות את רוב הצרכים המיידיים שלכם בשימוש ב dplyr
עם זאת, יש עוד כמה דברים שכדאי לדעת על הספריה שאין זמן לעבור על כולם. הנה שתיים מהבולטים:
select_helpers
_
אתם מוזמנים לחפש בעזרה ובאינטרנט….
יש שתי חבילות מובילות לשינוי מבנה הנתונים:
tidyr
- חבילה מה tidyverse שנועדה לסידור נתוניםreshape2
- חבילה יעודית לשחלוף נתוניםחבילת tidyr היא (בינתיים) קצת יותר מוגבלת בשחלוף נתונים
זאת כיוון שהיא נועדה לסדר נתונים בהתאם לפלוסופיה שהוזכרה לעיל
reshape2 נועד רק לשחלף נתונים ולכן הוא יותר גמיש
נכיר את שניהם בקצרה
tidyr
- שינוי מבנה הנתוניםהפקודות בספריית tidyr נועדו לעשות מנפולציות נפוצות על נתונים:
spread
- שחלוף נתונים מ long ל widegather
- שחלוף נתונים מ wide ל long
seperate
- חלוקת עמודה אחת למספר עומדותunite
- חיבור מספר עמודות לעמודה אחת
קודם נטעין את הספריה ונסתכל על הנתונים לדוגמא
library(tidyr)
## Warning: package 'tidyr' was built under R version 3.3.3
N_month_seg <- Santander_sample %>%
group_by(fecha_dato, segmento) %>%
summarise(sum_cc = sum(ind_cc),
n_pop = n())
N_month_seg <- ungroup(N_month_seg)
N_month_seg %>% slice(1:15)
fecha_dato | segmento | sum_cc | n_pop |
---|---|---|---|
2015-04-28 | 01 - TOP | 45 | 1569 |
2015-04-28 | 02 - PARTICULARES | 199 | 12448 |
2015-04-28 | 03 - UNIVERSITARIO | 15 | 4507 |
2015-07-28 | 01 - TOP | 50 | 1479 |
2015-07-28 | 02 - PARTICULARES | NA | 12614 |
2015-07-28 | 03 - UNIVERSITARIO | NA | 4510 |
2015-10-28 | 01 - TOP | 37 | 1547 |
2015-10-28 | 02 - PARTICULARES | NA | 13316 |
2015-10-28 | 03 - UNIVERSITARIO | NA | 5361 |
2016-01-28 | 01 - TOP | 41 | 1616 |
2016-01-28 | 02 - PARTICULARES | NA | 13543 |
2016-01-28 | 03 - UNIVERSITARIO | NA | 5882 |
2016-03-28 | 01 - TOP | 48 | 1723 |
2016-03-28 | 02 - PARTICULARES | NA | 13933 |
2016-03-28 | 03 - UNIVERSITARIO | 11 | 5952 |
gather
- מעבר מ wide ל longה syntax הבסיסי של הפקודה היא:
gather(data, key, value, …, na.rm = FALSE, convert = FALSE, factor_key = FALSE)
כאשר:
עכשיו נהפוך ל long בעזרת gather
N_month_seg.long <- N_month_seg %>%
gather(key = new_var_col
, value = new_value_col
, sum_cc:n_pop )
N_month_seg.long %>% slice(10:20)
fecha_dato | segmento | new_var_col | new_value_col |
---|---|---|---|
2016-01-28 | 01 - TOP | sum_cc | 41 |
2016-01-28 | 02 - PARTICULARES | sum_cc | NA |
2016-01-28 | 03 - UNIVERSITARIO | sum_cc | NA |
2016-03-28 | 01 - TOP | sum_cc | 48 |
2016-03-28 | 02 - PARTICULARES | sum_cc | NA |
2016-03-28 | 03 - UNIVERSITARIO | sum_cc | 11 |
2015-04-28 | 01 - TOP | n_pop | 1569 |
2015-04-28 | 02 - PARTICULARES | n_pop | 12448 |
2015-04-28 | 03 - UNIVERSITARIO | n_pop | 4507 |
2015-07-28 | 01 - TOP | n_pop | 1479 |
2015-07-28 | 02 - PARTICULARES | n_pop | 12614 |
spread
- מעבר מ long ל wideה syntax הבסיסי של הפקודה היא:
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)
כאשר:
ונחזיר חזרה ל wide בעזרת spread
:
N_month_seg.wide <- N_month_seg.long %>%
spread(key = new_var_col
, value = new_value_col )
N_month_seg.wide %>% slice(10:20)
fecha_dato | segmento | n_pop | sum_cc |
---|---|---|---|
2016-01-28 | 01 - TOP | 1616 | 41 |
2016-01-28 | 02 - PARTICULARES | 13543 | NA |
2016-01-28 | 03 - UNIVERSITARIO | 5882 | NA |
2016-03-28 | 01 - TOP | 1723 | 48 |
2016-03-28 | 02 - PARTICULARES | 13933 | NA |
2016-03-28 | 03 - UNIVERSITARIO | 5952 | 11 |
unite
- איחוד עמודותה syntax של הפקודה היא:
unite(data, col, …, sep = “_“, remove = TRUE)
כאשר:
נייצר משתנה חדש המפריד בין הרכיבים עם סימן _
כך:
N_month_seg.united <- N_month_seg %>%
unite(new_col_name
, fecha_dato , segmento
, sep="_"
, remove = TRUE)
N_month_seg.united %>% slice(20:25)
new_col_name sum_cc n_pop ————- ——- ——
שימו לב לפקודה remove = TRUE שמוחק את המשתנים המקוריים, כמובן שאפשר גם לשמור אותם
seperate
- פיצול עמודותה syntax של הפקודה היא:
separate(data, col, into, sep = “[^[:alnum:]]+”, remove = TRUE, convert = FALSE, extra = “warn”, fill = “warn”, …)
כאשר:
לחלק עמודה אחת למספר עמודות נשתמש ב seperate
כך:
# Back to the original
N_month_seg.seperated <- N_month_seg.united %>%
separate( new_col_name
, c("fecha_dato", "segmento")
, sep = "_" )
N_month_seg.seperated %>% slice(20:25)
fecha_dato segmento sum_cc n_pop ———– ——— ——- ——
reshape2
- שינוי מבנה הנתוניםהפקודות החשובות בחבילה הן :
melt
- מעבר מ wide ל longdcast
- מעבר מ long ל widemelt
- מעבר מ wide ל longהסנטקס של הפקודה היא :
melt(data, id.vars, measure.vars, variable.name = “variable”, value.name = “value”, factorsAsStrings = TRUE)
כאשר:
factor
ל chr
עכשיו נהפוך ל long בעזרת melt
library(reshape2)
##
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
##
## smiths
N_month_seg.long <- N_month_seg %>%
melt( id.vars = c("fecha_dato", "segmento")
, variable.name = "new_var_col"
, value.name = "new_value_col"
, factorsAsStrings = FALSE )
N_month_seg.long %>% slice(60:65)
fecha_dato segmento new_var_col new_value_col ———– ——— ———— ————–
שימו לב שלא ציינתי את הפרמט measure.vars
, במקרה כזה הוא לוקח את כל העמודות שלא ב `id.vars``
או לפי מספר עמודות למשל 3:5
dcast
- מעבר מ long ל wideהסנטקס המקוצר של הפקודה היא :
dcast(data, formula, fun.aggregate = NULL, …, margins = NULL, value.var = guess_value(data), fill = NULL)
כאשר:
ה syntax של הפרמטר formula
הוא:
key_col1 + key_col2 ~ val1 + val2
בדוגמא שלנו המפתחות הייחודיות הם: fecha_dato ו segmento
עכשיו נהפוך ל wide בעזרת dcast
N_month_seg.wide <- N_month_seg.long %>%
dcast( fecha_dato + segmento ~ new_var_col
, value.var = "new_value_col"
, fun.aggregate = mean )
N_month_seg.wide %>% slice(10:20)
fecha_dato | segmento | sum_cc | n_pop |
---|---|---|---|
2016-01-28 | 01 - TOP | 41 | 1616 |
2016-01-28 | 02 - PARTICULARES | NA | 13543 |
2016-01-28 | 03 - UNIVERSITARIO | NA | 5882 |
2016-03-28 | 01 - TOP | 48 | 1723 |
2016-03-28 | 02 - PARTICULARES | NA | 13933 |
2016-03-28 | 03 - UNIVERSITARIO | 11 | 5952 |
fun.aggregate
במקרים של ריבוי תצפיות לפי מפתח הוא עושה אגרגציה לפי בחירה
עוד אופציה נחמדה היא fill
המאפשר הצבת ערכי ברירת מחדל במקום ערכים חסרים