בשיעור הזה נתמקד בעבודה עם טבלאות נתונים - data frame. רוב העבודה שלכם מול R תהיה בעזרת טבלאות נתונים המניחים מבנה מסוים לנתונים שאותם מנתחים. בשיעור הזה נלמד איך לעבוד עם טבלאות בשפת הבסיס של R אבל בשיעורים הבאים נעשה שימוש בספריות חיצוניות כגון dplyr
ו sqldf
המקלות מאוד על עבודה עם טבלאות נתונים.
עד סוף השיעור תדעו:
הרעיון מאחורי טבלת נתונים היא שכל שורה בטלה מייצגת תצפית ברמת ניתוח מסוימת, ועמודות הטבלה מכילים מאפיינים שונים עבור אותה תצפית. הרעיון של טבלת נתונים מיושם ב R בעזרת אובייקט ה data.frame שניתן לחשוב עליה ולגשת עליה בכמה אופנים:
כאמור, בכל סוגי המבנים ניתן לגשת לנתונים באחד מ 3 דרכים:
בהמשך השיעור נתן דוגמאות על טבלת iris
המובנית בתוך R
קודם בא נשמור גרסא מקומית של אותו טבלה שעליה נוכל להדגים:
irisdata <- iris
כאמור, טבלה היא סוג של מטריצה, וכל הכללים שלמדנו בשיעור הקודם על גישה לנותנים במטריצות חלים גם כאן.
TableName[Row Index, Coloumn Index]
לדוגמא:
# Rows 1 to 5; Coloumns 1,3,4
irisdata[1:5, c(1,3,4)]
Sepal.Length | Petal.Length | Petal.Width |
---|---|---|
5.1 | 1.4 | 0.2 |
4.9 | 1.4 | 0.2 |
4.7 | 1.3 | 0.2 |
4.6 | 1.5 | 0.2 |
5.0 | 1.4 | 0.2 |
לדוגמא:
irisdata[1:2, 2:3] <- NA
irisdata[1:5, c(1,2,3)]
Sepal.Length | Sepal.Width | Petal.Length |
---|---|---|
5.1 | NA | NA |
4.9 | NA | NA |
4.7 | 3.2 | 1.3 |
4.6 | 3.1 | 1.5 |
5.0 | 3.6 | 1.4 |
כמו בוקטורים ומטריצות ניתן לבחור לפי תנאי. בדרך כלל נרצה לשים תנאי על עמודה מסוימת, על זה נלמד בהמשך השיעור. אבל אחד הפעולות הנפוצות לבצע על תנאי על טבלה שלמה היא לטיפול בערכים חסרים או להחליף ערך מסוים הנמצא בכל הטבלה. הפקודה is.na מחזיר ערך לוגי לכל ערך בווקטור, TRUE עם הערך חסר ו FALSE עם הערך לא חסר.
# Replace Missing data with default value
irisdata[is.na(irisdata)] <- 9999
irisdata[1:5, c(1,2,3)]
Sepal.Length | Sepal.Width | Petal.Length |
---|---|---|
5.1 | 9999.0 | 9999.0 |
4.9 | 9999.0 | 9999.0 |
4.7 | 3.2 | 1.3 |
4.6 | 3.1 | 1.5 |
5.0 | 3.6 | 1.4 |
גם במטריצות ווקטורים ניתן לתת שמות לעמודות ולשורות, עם זאת האובייקט הנפוץ ביותר לשימוש בשמות הוא טבלה data.frame המקשר בין וקטורים שונים.
ה syntax לשלוף נתון מתוך טבלה היא:
TableName$ColumnName[RowNumber]
לדוגמא:
# Show the first 5 values
irisdata$Sepal.Length[1:5]
## [1] 5.1 4.9 4.7 4.6 5.0
# We can use a coloumn directly like any other vector
hist(irisdata$Sepal.Length)
כמו בכל דבר ב R , הכוח האמיתי בא כשמשלבים בין השיטות השונות של גישה לטבלאות. כלומר גם גישה לטבלה עם שמות עמודות וגם כמטריצה לפי מקום ותנאים.
עכשיו שהבנו את העקרונות של גישה לטבלאות בוא נראה איך אפשר לשלב ביניהם לבצע שאילתות על הטבלה.
לבחירת שאילתא על טבלה, מכניסים את התנאי למקום הראשון ואת העמודה שרוצים בחזרה במקום השני.
Table[Condition, Columns]
# One Coloumn
irisdata[irisdata$Sepal.Length>7.6,1]
## [1] 7.7 7.7 7.7 7.9 7.7
:
# Consecutive Coloumns
irisdata[irisdata$Sepal.Length>7.6,1:3]
Sepal.Length | Sepal.Width | Petal.Length | |
---|---|---|---|
118 | 7.7 | 3.8 | 6.7 |
119 | 7.7 | 2.6 | 6.9 |
123 | 7.7 | 2.8 | 6.7 |
132 | 7.9 | 3.8 | 6.4 |
136 | 7.7 | 3.0 | 6.1 |
c
# Specific Coloumns
irisdata[irisdata$Sepal.Length>7.6,c(1,3,5)]
Sepal.Length | Petal.Length | Species | |
---|---|---|---|
118 | 7.7 | 6.7 | virginica |
119 | 7.7 | 6.9 | virginica |
123 | 7.7 | 6.7 | virginica |
132 | 7.9 | 6.4 | virginica |
136 | 7.7 | 6.1 | virginica |
# One Coloumn
## Option 1
irisdata[irisdata$Sepal.Length>7.6,"Sepal.Length"]
## [1] 7.7 7.7 7.7 7.9 7.7
## Option 2
irisdata$Sepal.Length[irisdata$Sepal.Length>7.6]
## [1] 7.7 7.7 7.7 7.9 7.7
# Multiple Coloumns
irisdata[irisdata$Sepal.Length>7.6,c("Species", "Sepal.Length","Sepal.Width")]
Species | Sepal.Length | Sepal.Width | |
---|---|---|---|
118 | virginica | 7.7 | 3.8 |
119 | virginica | 7.7 | 2.6 |
123 | virginica | 7.7 | 2.8 |
132 | virginica | 7.9 | 3.8 |
136 | virginica | 7.7 | 3.0 |
irisdata[irisdata$Sepal.Length>7.6,]
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | |
---|---|---|---|---|---|
118 | 7.7 | 3.8 | 6.7 | 2.2 | virginica |
119 | 7.7 | 2.6 | 6.9 | 2.3 | virginica |
123 | 7.7 | 2.8 | 6.7 | 2.0 | virginica |
132 | 7.9 | 3.8 | 6.4 | 2.0 | virginica |
136 | 7.7 | 3.0 | 6.1 | 2.3 | virginica |
החלפת ערכים בעמודה מסוימת כשהשורה עומדת בתנאי מסוים נעשית באותו שיטה.
# Replace
irisdata[irisdata$Sepal.Length>7.6,c("Sepal.Length","Sepal.Width")] <- 9999
# Show
irisdata[irisdata$Sepal.Length>7.6,]
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | |
---|---|---|---|---|---|
118 | 9999 | 9999 | 6.7 | 2.2 | virginica |
119 | 9999 | 9999 | 6.9 | 2.3 | virginica |
123 | 9999 | 9999 | 6.7 | 2.0 | virginica |
132 | 9999 | 9999 | 6.4 | 2.0 | virginica |
136 | 9999 | 9999 | 6.1 | 2.3 | virginica |
subset
כיוון ששאילתא בסיסית היא פעולה נפוצה , קיימת ב R פונקציה בשם subset, המקלה על כתיבת השאילתא:
מבנה הפקודה היא:
subset(TableName, Condition, Coloumns)
למשל:
subset(irisdata, Sepal.Width==9999, c("Sepal.Length","Sepal.Width"))
Sepal.Length | Sepal.Width | |
---|---|---|
1 | 5.1 | 9999 |
2 | 4.9 | 9999 |
118 | 9999.0 | 9999 |
119 | 9999.0 | 9999 |
123 | 9999.0 | 9999 |
132 | 9999.0 | 9999 |
136 | 9999.0 | 9999 |
בתוך ה c
בבחירת העמודות לא חייבים את הגרשיים אבל זה מקרה יוצא דופן
פעולה נפוצה מאוד בניתוח נתונים היא לבצע סטטיסטיקות שונות לפי רמות של משתנה מסוים.
הדרך לעשות זאת ב R היא להשתמש באחד הפקודות הבאות המובדלים באובייקט שהן מחזירות ובהתאם במספר הפונקציות שהן יכולות לבצע במקביל.
tapply
פקודה ממשפחת ה apply
שמבצעות איזשהו פעולה על כל ערך ברשימה. שתי הפקודות הבאות בנויות על פקודה זו. בהמשך הקורס נבין בדיוק איך הפקודה הזו עובדת.
tapply(Table$Coloumn, Table$GroupColoumn, Computation)
by
by(Table$Coloumn, Table$GroupColoumn, Computation)
aggregate
aggregate(Table$Coloumn, Table$GroupColoumn, Computation)
# Or
aggregate(Coloumn ~ GroupColoumn, data = Table, Computation)
aggregate(cbind(Table$Col1,Table$Col2), Table$GroupColoumn, Computation)
# Or
aggregate(cbind(Col1,Col2) ~ GroupColoumn, data = Table, Computation)
aggregate(Table$Coloumn, list(Table$Group1,Table$Group2), Computation)
# Or
aggregate(Coloumn ~ Group1 + Group2, data = Table, Computation)
לרוב נשתמש בפקודה aggregate
כי היא נוחה יותר בעבודה עם טבלאות.
הסינטקס של aggregate
הוא בסגנון נוסחא של R ועוד נתקל בה בהמשך
בדוגמא הבאה נבצע את אותו חישובים לפי כל אחד מהפונקציות הללו:
tapply(irisdata$Sepal.Length, irisdata$Species, summary)
## $setosa
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.300 4.800 5.000 5.006 5.200 5.800
##
## $versicolor
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.900 5.600 5.900 5.936 6.300 7.000
##
## $virginica
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.900 6.225 6.500 1006.000 6.900 9999.000
by(irisdata$Sepal.Length, irisdata$Species, summary)
## irisdata$Species: setosa
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.300 4.800 5.000 5.006 5.200 5.800
## --------------------------------------------------------
## irisdata$Species: versicolor
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.900 5.600 5.900 5.936 6.300 7.000
## --------------------------------------------------------
## irisdata$Species: virginica
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.900 6.225 6.500 1006.000 6.900 9999.000
aggregate(Sepal.Length ~ Species, data = irisdata, mean)
Species | Sepal.Length |
---|---|
setosa | 5.006 |
versicolor | 5.936 |
virginica | 1005.714 |
השינויים הבסיסיים שנרצה לבצע על טבלה הינם:
אפשר להוסיף עוד עמודה או דרך חישוב ישיר או על ידי הוספת וקטור בתור עוד עמודה בטבלה.
ניתן להוסיף עמודה בצורה ישירה לפי הסינטקס הבא:
Table$Column <- Value
לדוגמא:
# Add a constant value of 5
irisdata$NewCol <- 5
head(irisdata)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | NewCol |
---|---|---|---|---|---|
5.1 | 9999.0 | 9999.0 | 0.2 | setosa | 5 |
4.9 | 9999.0 | 9999.0 | 0.2 | setosa | 5 |
4.7 | 3.2 | 1.3 | 0.2 | setosa | 5 |
4.6 | 3.1 | 1.5 | 0.2 | setosa | 5 |
5.0 | 3.6 | 1.4 | 0.2 | setosa | 5 |
5.4 | 3.9 | 1.7 | 0.4 | setosa | 5 |
לדוגמא לחשב את היחס בין אורך עלה לבין הרוחב שלו:
irisdata$NewCol <- irisdata$Sepal.Length/irisdata$Sepal.Width
head(irisdata)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | NewCol |
---|---|---|---|---|---|
5.1 | 9999.0 | 9999.0 | 0.2 | setosa | 0.0005101 |
4.9 | 9999.0 | 9999.0 | 0.2 | setosa | 0.0004900 |
4.7 | 3.2 | 1.3 | 0.2 | setosa | 1.4687500 |
4.6 | 3.1 | 1.5 | 0.2 | setosa | 1.4838710 |
5.0 | 3.6 | 1.4 | 0.2 | setosa | 1.3888889 |
5.4 | 3.9 | 1.7 | 0.4 | setosa | 1.3846154 |
לחלופין ניתן לאגד בין טבלה קיימת לוקטור קיים בעל אותו אורך בעזרת פקודת cbind
הסינטקס הבסיסי של הפקודה נתונה על ידי:
cbind(Table1, Table2)
לדוגמא:
# Make a vector
NewCol2 <- 1:150
# Bind the table
irisdata <- cbind(irisdata, NewCol2)
head(irisdata)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | NewCol | NewCol2 |
---|---|---|---|---|---|---|
5.1 | 9999.0 | 9999.0 | 0.2 | setosa | 0.0005101 | 1 |
4.9 | 9999.0 | 9999.0 | 0.2 | setosa | 0.0004900 | 2 |
4.7 | 3.2 | 1.3 | 0.2 | setosa | 1.4687500 | 3 |
4.6 | 3.1 | 1.5 | 0.2 | setosa | 1.4838710 | 4 |
5.0 | 3.6 | 1.4 | 0.2 | setosa | 1.3888889 | 5 |
5.4 | 3.9 | 1.7 | 0.4 | setosa | 1.3846154 | 6 |
מחיקת עמודה נעשית בצורה ישירה על ידי השמת הערך NULL
במקום העמודה בצורה הבאה:
Table$Column <- NULL
לדוגמא:
irisdata$NewCol <- NULL
str(irisdata)
## 'data.frame': 150 obs. of 6 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 9999 9999 3.2 3.1 3.6 ...
## $ Petal.Length: num 9999 9999 1.3 1.5 1.4 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ NewCol2 : int 1 2 3 4 5 6 7 8 9 10 ...
שימו לב: השמת הערך NA
במקום הערך NULL
תחליף את תכולת העמודה בערך חסר
שינויים בשמות עמודות תעשה בעזרת הפקודה names
.
names
תחזיר לנו וקטור עם שמות העמודות לפי סדר הופעתן בטבלה בצורה הבאה:names(TableName)
names(TableName) <- c("Name1","Name2",...)
names(TableName)[Column Index] <- "New Name"
names(TableName)[c(Column Indices)] <- c("Name1","Name2",...)
לדוגמא:
# Save the Names of the Coloumns
originalNames <- names(irisdata)
originalNames
## [1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width"
## [5] "Species" "NewCol2"
# Rename Coloumns 1 and 3
names(irisdata)[c(1,3)] <- c("Var1", "Var3")
names(irisdata)
## [1] "Var1" "Sepal.Width" "Var3" "Petal.Width" "Species"
## [6] "NewCol2"
# Rename Coloumn 4
names(irisdata)[4] <- "Col4"
names(irisdata)
## [1] "Var1" "Sepal.Width" "Var3" "Col4" "Species"
## [6] "NewCol2"
# Rename All Coloumns back to original
names(irisdata) <- originalNames
names(irisdata)
## [1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width"
## [5] "Species" "NewCol2"
ב R ניתן למיין את הטבלה בעזרת הפקודה order
וגישה לטבלה כפי שניגשנו למטריצות.
TableName[order(TableName$Coloumn),]
TableName[order(TableName$Coloumn1,TableName$Coloumn2),]
-
לפני שם המשתנה, לדוגמא:TableName[order(TableName$Coloumn1, -TableName$Coloumn2),]
לדוגמא:
irisdata <- irisdata[order(irisdata$Sepal.Length, -irisdata$Sepal.Width),]
head(irisdata)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | NewCol2 | |
---|---|---|---|---|---|---|
14 | 4.3 | 3.0 | 1.1 | 0.1 | setosa | 14 |
43 | 4.4 | 3.2 | 1.3 | 0.2 | setosa | 43 |
39 | 4.4 | 3.0 | 1.3 | 0.2 | setosa | 39 |
9 | 4.4 | 2.9 | 1.4 | 0.2 | setosa | 9 |
42 | 4.5 | 2.3 | 1.3 | 0.3 | setosa | 42 |
23 | 4.6 | 3.6 | 1.0 | 0.2 | setosa | 23 |
ישנם שתי פעולות עיקריות שנרצה לבצע עבור מספר טבלאות. איחוד טבלאות (union) , וסוגים שונים של חיבור בין טבלאות (join)
ניתן לאחד בין טבלאות בעזרת הפקודה הפשוטה rbind
שהיא בעצם ביצוע union
בין שתי טבלאות או יותר. הסינטקס הבסיסי של הפקודה נתונה על ידי:
rbind(Table1, Table2)
לדגמא:
irisdata2 <- rbind(irisdata, irisdata)
# Return the dimensions of the tables
dim(irisdata)
## [1] 150 6
dim(irisdata2)
## [1] 300 6
חיבור בין טבלאות היא בליבה של עולם הטבלאות הרלציוני, ומהותה היא איחוד בין טבלאות שונות בעזרת מפתח משותף. בשפת ה SQL הפעולה מתבצעת בעזרת פעולות Join למיניהם.
בשפה הבסיסית של R ניתן לבצע את פעולת האיחוד בעזרת הפקודה merge
לפי הסינטקס הבא:
merge(Table A, Table B,
by.x ="KeyTableA" , by.y ="KeyTableB" ,
all.x = TRUE/FALSE, all.y =TRUE/FALSE )
זאת כאשר הפרמטרים all.x
ו all.y
קובעות לנו את סוג החיבור בין הטבלאות. להלן טבלה המקשרת בין האפשרויות השונות לבין פעולת ה join
בשפת ה SQL:
בשביל להדגים, קודם:
Sepal.Length
לפי העמודה Species
MeanLength
setosa
בעמודת המפתח Species
בערך NA# Calculate aggregated table
irisMean <- aggregate(Sepal.Length ~ Species, data = irisdata, mean)
# Rename the Calculated Coloumn
names(irisMean)[2] <- "MeanLength"
# Replace setosa with NA
irisMean$Species[irisMean$Species=="setosa"] <- NA
Species
# Do a left join
irisdata <- merge(irisdata, irisMean,
by.x = "Species", by.y = "Species",
all.x = TRUE,
all.y = FALSE)
irisdata[48:53,]
Species | Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | NewCol2 | MeanLength | |
---|---|---|---|---|---|---|---|
48 | setosa | 5.4 | 3.4 | 1.7 | 0.2 | 21 | NA |
49 | setosa | 5.7 | 3.8 | 1.7 | 0.3 | 19 | NA |
50 | setosa | 5.7 | 4.4 | 1.5 | 0.4 | 16 | NA |
51 | versicolor | 5.9 | 3.0 | 4.2 | 1.5 | 62 | 5.936 |
52 | versicolor | 5.2 | 2.7 | 3.9 | 1.4 | 60 | 5.936 |
53 | versicolor | 6.0 | 2.9 | 4.5 | 1.5 | 79 | 5.936 |
בתרגיל הבא תעשו שימוש במה שלמדתם ותעזרו בפקודות הבאות על מנת לענות על השאלות:
summary
: פקודה המחזירה סטטיסטיקה בסיסית על טבלה או וקטורtable
: פקודה גנרית המחזירה טבלת התפלגות של וקטור על וקטור (ספירה של עמודה אחת מול השניה)prop.table
: מקבל אובייקט שנוצר מפקודת table
. ומקבל עוד פרמטר מספר 1 עד 3 לפיו מחזיר את שיעור הערכים לפי שורה (1) , עמודה (2), או סך הכלlevels
: מחזיר את הקטגוריות היחודיות עבור משתנה מסוג factor
mean
: חישוב ממוצע של וקטור / עמודהplot
: פקודה גנרית המייצרת גרף בהתאם לאובייקטים המעוברים עליהls
: מחזיר רשימה של שמות האובייקטים הקיימים בסביבה מסוימתrm
: מחיקת משתנהוכל פקודה אחרת שתשיג את המטרה…
העזרו ב help
אם אתם לא יודעים איך להשתמש בפקודה מסוימת
iris
לתוך אובייקט בשם iris_data
. התבוננו במבנה הנתונים שיצרתם. מה הרמות הייחודיות של העמודה Species
?Sepal.Length
?Species
יש ערך Sepal.Length
גדול מ 5 ?Sepal.Length
מול Sepal.Width
Grp_Length
שמבקל את הערך 1 עבור Sepal.Length
גדול מ 5 ו 0 אחרת. בדקו את עצמכם בעזרת הפקודה aggregate
Grp_Length
ו Species
ושמרו את התוצאה באוביקט בשם sumTable
prop.table
על האובייקט sumTable
לחשב, פעם אחת את האחוזים לפי שורות, פעם אחת את האחוזים לפי עמודות, ופעם אחת את האחוזים בטבלהSepal.Length
לערך חסר במקרים בהן Grp_Length
שווה ל 0. חישבו ממוצע על המשתנה החדשGrp_Length
ls
על מנת לקבל את שמות המשתנים הקיימים. תנקו את אזור העבודה שלכם מנתונים.iris_data <- iris
str(iris_data)
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
levels(iris_data$Species)
## [1] "setosa" "versicolor" "virginica"
summary(iris_data)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | |
---|---|---|---|---|---|
Min. :4.300 | Min. :2.000 | Min. :1.000 | Min. :0.100 | setosa :50 | |
1st Qu.:5.100 | 1st Qu.:2.800 | 1st Qu.:1.600 | 1st Qu.:0.300 | versicolor:50 | |
Median :5.800 | Median :3.000 | Median :4.350 | Median :1.300 | virginica :50 | |
Mean :5.843 | Mean :3.057 | Mean :3.758 | Mean :1.199 | NA | |
3rd Qu.:6.400 | 3rd Qu.:3.300 | 3rd Qu.:5.100 | 3rd Qu.:1.800 | NA | |
Max. :7.900 | Max. :4.400 | Max. :6.900 | Max. :2.500 | NA |
# This does not give the expected result!!
# And worse - Doesnt throw an Error!!
table(iris_data["Sepal.Length">5,"Species"])
setosa | versicolor | virginica |
---|---|---|
50 | 50 | 50 |
# Option 1
table(iris_data[iris_data$Sepal.Length>5,"Species"])
setosa | versicolor | virginica |
---|---|---|
22 | 47 | 49 |
# Option 2
table(subset(iris_data, Sepal.Length>5, c("Species")))
setosa | versicolor | virginica |
---|---|---|
22 | 47 | 49 |
plot(iris_data$Sepal.Length, iris_data$Sepal.Width)
iris_data$Grp_Length <- 0
iris_data$Grp_Length[iris_data$Sepal.Length>=5] <- 1
# Lets look at a summary to make sure we are right
aggregate(Sepal.Length ~ Grp_Length, data =iris_data, max)
Grp_Length | Sepal.Length |
---|---|
0 | 4.9 |
1 | 7.9 |
sumTable <- table(iris_data$Species, iris_data$Grp_Length)
prop.table(sumTable,1)
/ | 0 | 1 |
---|---|---|
setosa | 0.40 | 0.60 |
versicolor | 0.02 | 0.98 |
virginica | 0.02 | 0.98 |
prop.table(sumTable,2)
/ | 0 | 1 |
---|---|---|
setosa | 0.9090909 | 0.2343750 |
versicolor | 0.0454545 | 0.3828125 |
virginica | 0.0454545 | 0.3828125 |
prop.table(sumTable)
/ | 0 | 1 |
---|---|---|
setosa | 0.1333333 | 0.2000000 |
versicolor | 0.0066667 | 0.3266667 |
virginica | 0.0066667 | 0.3266667 |
iris_data$Sepal.Length[iris_data$Grp_Length == 0] <- NA
# Unpredictable NA actions
# This returns the expected answer
summary(iris_data$Sepal.Length)
Min. | 1st Qu. | Median | Mean | 3rd Qu. | Max. | NA’s |
---|---|---|---|---|---|---|
5 | 5.5 | 6 | 6.041 | 6.5 | 7.9 | 22 |
# This doesnt return the expected answer
mean(iris_data$Sepal.Length)
## [1] NA
# This does
mean(iris_data$Sepal.Length, na.rm = TRUE)
## [1] 6.041406
# Option 1
iris_data$Grp_Length <- NULL
# Option 2
iris_data <- iris_data[,-6]
1:5
## [1] 1 2 3 4 5
1:2
## [1] 1 2
1:5 + 1:2
## Warning in 1:5 + 1:2: longer object length is not a multiple of shorter
## object length
## [1] 2 4 4 6 6
# See whats going on - recycling...
# get a list of whats in the current environment
ls()
## [1] "iris_data" "irisdata" "irisdata2" "irisMean"
## [5] "NewCol2" "originalNames" "sumTable"
# this erases everything in our environment
rm(list = ls(.GlobalEnv))
“Advanced R, Hadley Wickham, Chapters 1-4” at http://adv-r.had.co.nz/
“The R Inferno, Patrick Burns, Chapter 8” at http://www.burns-stat.com/documents/books/the-r-inferno/