├── .gitignore ├── README.md ├── img ├── author_image.png └── shield_image.png ├── datasets ├── luffy_event.RData ├── straw_hat_df.RData ├── luffy_event_bounty.RData └── straw_hat_devil_fruit.RData ├── requirements.r ├── course.yml ├── removed └── removed.Rmd ├── chapter1.md ├── chapter5.md ├── chapter4.md ├── chapter2.md └── chapter3.md /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user/* 2 | .Rproj.user 3 | .cache 4 | .DS_STORE 5 | .Rhistory 6 | .RData 7 | .Rdata 8 | .rdata 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dataframe Manipulation in R (Chinese) 2 | 3 | Community course on Dataframe manipulation in Cantonese. 4 | -------------------------------------------------------------------------------- /img/author_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/community-courses-dataframe-manipulation-r-chinese/master/img/author_image.png -------------------------------------------------------------------------------- /img/shield_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/community-courses-dataframe-manipulation-r-chinese/master/img/shield_image.png -------------------------------------------------------------------------------- /datasets/luffy_event.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/community-courses-dataframe-manipulation-r-chinese/master/datasets/luffy_event.RData -------------------------------------------------------------------------------- /datasets/straw_hat_df.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/community-courses-dataframe-manipulation-r-chinese/master/datasets/straw_hat_df.RData -------------------------------------------------------------------------------- /datasets/luffy_event_bounty.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/community-courses-dataframe-manipulation-r-chinese/master/datasets/luffy_event_bounty.RData -------------------------------------------------------------------------------- /datasets/straw_hat_devil_fruit.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/community-courses-dataframe-manipulation-r-chinese/master/datasets/straw_hat_devil_fruit.RData -------------------------------------------------------------------------------- /requirements.r: -------------------------------------------------------------------------------- 1 | devtools::install_version("tibble", "1.4.2") 2 | devtools::install_version("plyr", "1.8.4") 3 | devtools::install_version("dplyr", "0.7.4") 4 | devtools::install_version("tidyr", "0.8.0") 5 | -------------------------------------------------------------------------------- /course.yml: -------------------------------------------------------------------------------- 1 | title : 資料框整理技巧 2 | author_field : Tony Yao-Jen Kuo 3 | description : 在 R 語言導論中我們介紹了一種資料類型叫資料框,實務中我們面對的多數資料分析專案都是將原始資料讀為一個資料框再開始進行後續工作。我們將在這門課程中跟著草帽海賊團在新世界冒險,一邊學習各種資料框整理技巧,像是欄與列的技巧、生成衍生變數、轉置以及聯結等,努力成為懸賞金額破億的超新星海賊,一場爭奪 One Piece 的海上冒險故事! 4 | university : DataCamp 5 | difficulty_level : 2 6 | time_needed : 2 hours 7 | author_bio: "郭耀仁畢業於臺灣大學商學研究所碩士班,是資料科學與推廣教育的愛好者。目前是新創公司 Kyosei 的共同創辦人;同時亦是臺大系統訓練班的講師成員,推廣資料科學,R 語言與 Python, 8 | 班上熱心的學員是協助校正中文課程的得力助手。在 Kyosei 之前是 Coupang 的資料分析師與 SAS 分析顧問。 9 | 閒暇時熱愛長跑與乒乓球,參加 2016 年波士頓馬拉松時初次拜訪 DataCamp,與我們一同討論課程的中文化與資料科學的推廣。 10 |
11 |
12 | Yao-Jen is enthusiastic about data science and education. 13 | He is now one of the co-founders at Kyosei, a startup focusing on light-weight data science solutions. 14 | He lectures on \"Data Science and R/Python\" at System Training Program of NTU. 15 | Active students in class helps him elaborate the localized courses. 16 | Prior to founding Kyosei, he was a senior data analyst at Coupang and an analytical consultant at SAS Software. 17 | He holds a M.B.A. at NTU, however, his career so far is quite different from most of his peers. 18 | In his spare time, he enjoys Marathons and ping-pong. In fact, the first time we met him was the 2016 Boston Marathon. 19 | He came to our office after the race and discussed localization of our courses." 20 | from: 'r-base-prod:27' 21 | -------------------------------------------------------------------------------- /removed/removed.Rmd: -------------------------------------------------------------------------------- 1 | --- type:NormalExercise lang:r xp:100 skills:4 key:1a1353d859 2 | ## 寫 SQL 查詢 3 | 4 | 走到這裡,你已經是一位能夠自在使用 R 語言整理資料框的高額賞金海賊!最後一個練習我們介紹 R 語言的 [`sqldf`](http://www.rdocumentation.org/packages/sqldf/versions/0.4-7.1) 套件,載入套件以後你就可以使用 [`sqldf()`](http://www.rdocumentation.org/packages/sqldf/versions/0.4-7.1/topics/sqldf) 函數,它能夠讓你寫 SQL 查詢來整理資料框,這對原本就擅長使用 SQL 查詢語法的海賊們無疑是個天大好消息! 5 | 6 | ```{r} 7 | library(sqldf) 8 | sqldf("your sql query here...") 9 | ``` 10 | 11 | *** =instructions 12 | - 完成第一個 SQL 查詢將草帽海賊團賞金高於 1 億貝里的船員選出來,並指派給一個資料框 `straw_hat_high_bounty`。 13 | - 將 `straw_hat_high_bounty` 輸出在 R Console。 14 | - 完成第二個 SQL 查詢將角色設定與惡魔果實資料框做**左外部聯結** (LEFT JOIN),並指派給一個資料框 `straw_hat_df_devil_fruit`。 15 | - 將 `straw_hat_df_devil_fruit` 輸出在 R Console。 16 | 17 | *** =hint 18 | - 第一個查詢 `WHERE` 條件要下為 `WHERE bounty > 100000000`。 19 | - 第二個查詢要輸入 `LEFT JOIN straw_hat_devil_fruit ON straw_hat_df.name = straw_hat_devil_fruit.name` 20 | 21 | *** =pre_exercise_code 22 | ```{r} 23 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 24 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_devil_fruit.RData")) 25 | ``` 26 | 27 | *** =sample_code 28 | ```{r} 29 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 30 | 31 | # 載入 sqldf 套件 32 | library(sqldf) 33 | 34 | # 第一個查詢 35 | straw_hat_high_bounty <- sqldf("SELECT * FROM straw_hat_df WHERE __ > __") 36 | 37 | # 將 straw_hat_high_bounty 輸出在 R Console 38 | 39 | 40 | # 第二個查詢 41 | straw_hat_df_devil_fruit <- sqldf("SELECT straw_hat_df.*, straw_hat_devil_fruit.devil_fruit, straw_hat_devil_fruit.devil_fruit_type FROM straw_hat_df __ __ straw_hat_devil_fruit ON straw_hat_df.__ = straw_hat_devil_fruit.__") 42 | 43 | # 將 straw_hat_df_devil_fruit 輸出在 R Console 44 | 45 | ``` 46 | 47 | *** =solution 48 | ```{r} 49 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 50 | 51 | # 載入 sqldf 套件 52 | library(sqldf) 53 | 54 | # 第一個查詢 55 | straw_hat_high_bounty <- sqldf("SELECT * FROM straw_hat_df WHERE bounty > 100000000") 56 | 57 | # 將 straw_hat_high_bounty 輸出在 R Console 58 | straw_hat_high_bounty 59 | 60 | # 第二個查詢 61 | straw_hat_df_devil_fruit <- sqldf("SELECT straw_hat_df.*, straw_hat_devil_fruit.devil_fruit, straw_hat_devil_fruit.devil_fruit_type FROM straw_hat_df LEFT JOIN straw_hat_devil_fruit ON straw_hat_df.name = straw_hat_devil_fruit.name") 62 | 63 | # 將 straw_hat_df_devil_fruit 輸出在 R Console 64 | straw_hat_df_devil_fruit 65 | ``` 66 | 67 | *** =sct 68 | ```{r} 69 | msg = "確認是否有在 `WHERE` 條件加入賞金高於 1 億貝里?" 70 | test_object("straw_hat_high_bounty", 71 | undefined_msg = msg, 72 | incorrect_msg = msg) 73 | 74 | msg = "確認是否有在 R Console 輸出 `straw_hat_high_bounty`?" 75 | test_output_contains("straw_hat_high_bounty", 76 | incorrect_msg = msg) 77 | 78 | msg = "確認是否有使用 `LEFT JOIN` 語法進行左外部聯結?" 79 | test_object("straw_hat_df_devil_fruit", 80 | undefined_msg = msg, 81 | incorrect_msg = msg) 82 | 83 | msg = "確認是否有在 R Console 輸出 `straw_hat_df_devil_fruit`?" 84 | test_output_contains("straw_hat_df_devil_fruit", 85 | incorrect_msg = msg) 86 | 87 | success_msg("恭喜你!你高超的資料框整理技巧已經被海軍列為重點通緝海賊,你的名號已經傳遍了新世界,一場爭奪 One Piece 的海上冒險故事!") 88 | ``` 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /chapter1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title_meta : 第一章 3 | title : 建立與探索資料框 4 | description : 在學習資料框的整理技巧之前,我們得先在 R 語言的工作環境中建立出可供我們練習的資料框才行,在本章我們首先會複習在 R 語言導論中學過的內容,像是建立一個資料框以及一些快速探索資料框的好用函數,一場爭奪 One Piece 的海上冒險故事! 5 | 6 | --- type:NormalExercise lang:r xp:100 skills:4 key:9a073c3931 7 | ## 建立資料框 8 | 9 | 本課程會用到很多 [R 語言導論](https://www.datacamp.com/community/open-courses/r-%E8%AA%9E%E8%A8%80%E5%B0%8E%E8%AB%96#gs.xZfVkjM)中的觀念與語法,非常建議你先去玩玩看 [R 語言導論](https://www.datacamp.com/community/open-courses/r-%E8%AA%9E%E8%A8%80%E5%B0%8E%E8%AB%96#gs.xZfVkjM)再開始本課程! 10 | 11 | 草帽海賊團主要角色設定有: 12 | 13 | - 姓名 14 | - 性別 15 | - 職業 16 | - 賞金 17 | - 年齡 18 | - 生日 19 | - 身高 20 | 21 | 建立資料框之前通常習慣先將各個欄位生成為向量,我們大概猜想得到姓名應該是字串型的向量,而年齡會是數值型的向量。資料框特性是可以容納不同的資料格式,這代表著我們可以生成一個資料框將草帽海賊團的角色設定記錄在其中。 22 | 23 | 資料來源:[One Piece Wiki](http://onepiece.wikia.com/wiki/Main_Page) 24 | 25 | *** =instructions 26 | - 使用 `data.frame()` 將右邊編輯區已經定義好的角色設定向量結合為一個資料框,並命名為 `straw_hat_df`。 27 | 28 | *** =hint 29 | - 在編輯區輸入 `straw_hat_df <- data.frame(name, gender, occupation, bounty, age, birthday, height)` 30 | 31 | *** =pre_exercise_code 32 | ```{r} 33 | # no pec 34 | ``` 35 | 36 | *** =sample_code 37 | ```{r} 38 | # 角色設定的向量 39 | name <- c("Monkey D. Luffy", "Roronoa Zoro", "Nami", "Usopp", "Vinsmoke Sanji", "Tony Tony Chopper", "Nico Robin", "Franky", "Brook") 40 | gender <- c("Male", "Male", "Female", "Male", "Male", "Male", "Female", "Male", "Male") 41 | occupation <- c("Captain", "Swordsman", "Navigator", "Sniper", "Cook", "Doctor", "Archaeologist", "Shipwright", "Musician") 42 | bounty <- c(500000000, 320000000, 66000000, 200000000, 177000000, 100, 130000000, 94000000, 83000000) 43 | age <- c(19, 21, 20, 19, 21, 17, 30, 36, 90) 44 | birthday <- c("05-05", "11-11", "07-03", "04-01", "03-02", "12-24", "02-06", "03-09", "04-03") 45 | height <- c(174, 181, 170, 176, 180, 90, 188, 240, 277) 46 | 47 | # 建立草帽海賊團角色設定的資料框 48 | straw_hat_df <- 49 | ``` 50 | 51 | *** =solution 52 | ```{r} 53 | # 角色設定的向量 54 | name <- c("Monkey D. Luffy", "Roronoa Zoro", "Nami", "Usopp", "Vinsmoke Sanji", "Tony Tony Chopper", "Nico Robin", "Franky", "Brook") 55 | gender <- c("Male", "Male", "Female", "Male", "Male", "Male", "Female", "Male", "Male") 56 | occupation <- c("Captain", "Swordsman", "Navigator", "Sniper", "Cook", "Doctor", "Archaeologist", "Shipwright", "Musician") 57 | bounty <- c(500000000, 320000000, 66000000, 200000000, 177000000, 100, 130000000, 94000000, 83000000) 58 | age <- c(19, 21, 20, 19, 21, 17, 30, 36, 90) 59 | birthday <- c("05-05", "11-11", "07-03", "04-01", "03-02", "12-24", "02-06", "03-09", "04-03") 60 | height <- c(174, 181, 170, 176, 180, 90, 188, 240, 277) 61 | 62 | # 建立草帽海賊團角色設定的資料框 63 | straw_hat_df <- data.frame(name, gender, occupation, bounty, age, birthday, height) 64 | ``` 65 | 66 | *** =sct 67 | ```{r} 68 | msg <- "不需要移除原本幫你定義好的向量喔!" 69 | 70 | test_object("name", undefined_msg = msg, incorrect_msg = msg) 71 | test_object("gender", undefined_msg = msg, incorrect_msg = msg) 72 | test_object("occupation", undefined_msg = msg, incorrect_msg = msg) 73 | test_object("bounty", undefined_msg = msg, incorrect_msg = msg) 74 | test_object("age", undefined_msg = msg, incorrect_msg = msg) 75 | test_object("birthday", undefined_msg = msg, incorrect_msg = msg) 76 | test_object("height", undefined_msg = msg, incorrect_msg = msg) 77 | 78 | test_object("straw_hat_df", incorrect_msg = "確認是否正確使用 `data.frame()` 函數並且將結果指派給 straw_hat_df?") 79 | 80 | success_msg("你做得太棒了,讓我們繼續下一個練習!") 81 | ``` 82 | 83 | --- type:NormalExercise lang:r xp:100 skills:4 key:cb3400c7e4 84 | ## 探索資料框 85 | 86 | 我們可以使用幾個好用的函數來快速探索一個資料框: 87 | 88 | - [`dim()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/dim) 函數 89 | - [`head()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/head) 函數 90 | - [`tail()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/head) 函數 91 | - [`str()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/str) 函數 92 | - [`summary()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/summary) 函數 93 | 94 | [`dim()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/dim) 函數會回傳資料框的列數與欄數;[`head()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/head) 函數會回傳資料框的前六列;[`tail()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/head) 函數會回傳資料框的後六列;[`str()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/str) 函數不僅會列出資料框的觀察值個數與變數個數,還會列出每個欄位的資料類型以及前幾個觀測值;[`summary()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/summary) 函數會回傳量值型變數的敘述性統計資料,以及類別型變數的屬性資料。 95 | 96 | *** =instructions 97 | - 使用這 5 個好用的函數探索已經載入工作環境的 `straw_hat_df`。 98 | 99 | *** =hint 100 | - 使用 `dim(straw_hat_df)` 、 `head(straw_hat_df)` 、 `tail(straw_hat_df)` 、 `str(straw_hat_df)` 與 `summary(straw_hat_df)` 探索資料框。 101 | 102 | *** =pre_exercise_code 103 | ```{r} 104 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 105 | ``` 106 | 107 | *** =sample_code 108 | ```{r} 109 | # straw_hat_df 已經預先載入 110 | 111 | # 對 straw_hat_df 使用 dim() 、 head() 、 tail() 、 str() 與 summary() 112 | 113 | ``` 114 | 115 | *** =solution 116 | ```{r} 117 | # straw_hat_df 已經預先載入 118 | 119 | # 對 straw_hat_df 使用 dim() 、 head() 、 tail() 、 str() 與 summary() 120 | dim(straw_hat_df) 121 | head(straw_hat_df) 122 | tail(straw_hat_df) 123 | str(straw_hat_df) 124 | summary(straw_hat_df) 125 | ``` 126 | 127 | *** =sct 128 | ```{r} 129 | test_output_contains("dim(straw_hat_df)", incorrect_msg = "確認是否正確對 `straw_hat_df` 使用 `dim()` 函數?") 130 | 131 | test_output_contains("head(straw_hat_df)", incorrect_msg = "確認是否正確對 `straw_hat_df` 使用 `head()` 函數?") 132 | 133 | test_output_contains("tail(straw_hat_df)", incorrect_msg = "確認是否正確對 `straw_hat_df` 使用 `tail()` 函數?") 134 | 135 | test_output_contains("str(straw_hat_df)", incorrect_msg = "確認是否正確對 `straw_hat_df` 使用 `str()` 函數?") 136 | 137 | test_output_contains("summary(straw_hat_df)", incorrect_msg = "確認是否正確對 `straw_hat_df` 使用 `summary()` 函數?") 138 | 139 | success_msg("太棒了,這些函數都非常實用,一定要把它們記起來!"); 140 | ``` 141 | 142 | --- type:NormalExercise lang:r xp:100 skills:4 key:92e28431f1 143 | ## 依據欄位排序資料框 144 | 145 | 有時候我們對於資料框的外觀與排列會有自己的意見,例如會希望依照字母順序或者年齡大小的方式排序,在 R 語言可以使用 [`order()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/order) 函數來實現: 146 | 147 | ```{r} 148 | df[order(df$col, decreasing = FALSE)] 149 | ``` 150 | 151 | [`order()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/order) 函數預設都是**遞增排序**,所以 `decreasing = ` 的參數預設為 `FALSE`,如果我們希望是**遞減排序**就必須將參數設為 `decreasing = TRUE`。 152 | 153 | *** =instructions 154 | - 用 `height` 遞增排序草帽海賊團資料框。 155 | - 用 `bounty` 遞減排序草帽海賊團資料框。 156 | 157 | *** =hint 158 | - 用 `height` 遞增排序時 `decreasing = ` 設為 `FALSE` 或者不指定參數沿用預設。 159 | - 用 `bounty` 遞減排序時 `decreasing = ` 設為 `TRUE`。 160 | 161 | *** =pre_exercise_code 162 | ```{r} 163 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 164 | ``` 165 | 166 | *** =sample_code 167 | ```{r} 168 | # straw_hat_df 已經預先載入 169 | 170 | # 用 height 遞增排序 171 | straw_hat_df[order(straw_hat_df$__, decreasing = __), ] 172 | 173 | # 用 bounty 遞減排序 174 | straw_hat_df[order(straw_hat_df$__, decreasing = __), ] 175 | 176 | ``` 177 | 178 | *** =solution 179 | ```{r} 180 | # straw_hat_df 已經預先載入 181 | 182 | # 用 height 遞增排序 183 | straw_hat_df[order(straw_hat_df$height, decreasing = FALSE), ] 184 | 185 | # 用 bounty 遞減排序 186 | straw_hat_df[order(straw_hat_df$bounty, decreasing = TRUE), ] 187 | 188 | ``` 189 | 190 | *** =sct 191 | ```{r} 192 | msg = "確認是否有使用 `order()` 函數對身高做遞增排序?" 193 | test_output_contains("straw_hat_df[order(straw_hat_df$height, decreasing = FALSE), ]", 194 | incorrect_msg = msg) 195 | 196 | msg = "確認是否有使用 `order()` 函數對賞金做遞減排序?" 197 | test_output_contains("straw_hat_df[order(straw_hat_df$bounty, decreasing = TRUE), ]", 198 | incorrect_msg = msg) 199 | 200 | success_msg("太好了,這些熱身練習對你而言一定都相當容易吧?準備好我們就要航向下一個島嶼囉!") 201 | ``` -------------------------------------------------------------------------------- /chapter5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title_meta : 第五章 3 | title : 聯結資料框 4 | description : 在一個資料分析專案中,資料可能散落在多個資料框中,因此對於資料框的聯結你必須要有清晰的認知,假如你使用過關聯式資料庫進行資料查詢,你在這章節的練習中會覺得駕輕就熟;假如你沒有使用過也不要緊,我們將在本章節學習這些技巧與概念,一場爭奪 One Piece 的海上冒險故事! 5 | 6 | --- type:NormalExercise lang:r xp:100 skills:4 key:4aa0c0c890 7 | ## 惡魔果實的資料框 8 | 9 | **惡魔果實**是海賊王世界的奇特果實,有「海上惡魔的化身」的別稱,可以讓食用者得到特殊能力,擁有惡魔果實的人普遍被叫作「惡魔果實能力者」。在草帽海賊團中有 4 個能力者,但你注意到我們並沒有一個欄位紀錄船員的惡魔果實資訊,於是你駭入海軍的機密資料庫取得了草帽海賊團的惡魔果實資料 `straw_hat_devil_fruit`。 10 | 11 | 資料來源:[One Piece Wiki](http://onepiece.wikia.com/wiki/Main_Page) 12 | 13 | *** =instructions 14 | - 將草帽海賊團的惡魔果實資料框輸出在 R Console。 15 | 16 | *** =hint 17 | - 在編輯區輸入 `straw_hat_devil_fruit` 即可。 18 | 19 | *** =pre_exercise_code 20 | ```{r} 21 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_devil_fruit.RData")) 22 | ``` 23 | 24 | *** =sample_code 25 | ```{r} 26 | # straw_hat_devil_fruit 已預先載入 27 | 28 | # 在 R Console 輸出 straw_hat_devil_fruit 29 | 30 | ``` 31 | 32 | *** =solution 33 | ```{r} 34 | # straw_hat_devil_fruit 已預先載入 35 | 36 | # 在 R Console 印出 straw_hat_devil_fruit 37 | straw_hat_devil_fruit 38 | ``` 39 | 40 | *** =sct 41 | ```{r} 42 | test_output_contains("straw_hat_devil_fruit", 43 | incorrect_msg = "確認你是否有把 `straw_hat_devil_fruit` 輸出在 R Console?") 44 | 45 | success_msg("對你這位被數千萬貝里懸賞的海賊而言這練習實在是一片蛋糕!") 46 | ``` 47 | 48 | --- type:NormalExercise lang:r xp:100 skills:4 key:84d7738b12 49 | ## 內部聯結 50 | 51 | 現在你手邊已經取得了 `straw_hat_devil_fruit`,接著你想要把惡魔果實的資訊加入原本的資料框中。R 語言使用 [`merge()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/merge) 函數來進行資料框的聯結,如果你沒有使用過關聯式資料資料庫,你可以想像一下 Excel 的 vlookup 函數功能。 52 | 53 | ```{r} 54 | merge(df1, df2, by = "foreign_key_column", ...) 55 | ``` 56 | 57 | `by = ` 參數要指定兩個資料框參照的欄位,由於我們的資料框要參照的欄位名稱是相同的: `name`,因此在使用 [`merge()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/merge) 函數時不需要指定 `by = ` 參數。 58 | 59 | 輸出的結果會保留兩個資料框中有參照到的觀測值,這就是俗稱的**內部聯結**! 60 | 61 | *** =instructions 62 | - 使用 `merge()` 函數聯結 `straw_hat_df` 與 `straw_hat_devil_fruit`,將聯結後資料框宣告為 `straw_hat_df_devil_fruit`。 63 | - 將 `straw_hat_df_devil_fruit` 輸出在 R Console。 64 | 65 | *** =hint 66 | - 輸入 `straw_hat_df_devil_fruit <- merge(straw_hat_df, straw_hat_devil_fruit)` 就可以完成。 67 | 68 | *** =pre_exercise_code 69 | ```{r} 70 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 71 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_devil_fruit.RData")) 72 | ``` 73 | 74 | *** =sample_code 75 | ```{r} 76 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 77 | 78 | # 聯結資料框 79 | straw_hat_df_devil_fruit <- 80 | 81 | # 將結果輸出在 R Console 82 | 83 | ``` 84 | 85 | *** =solution 86 | ```{r} 87 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 88 | 89 | # 聯結資料框 90 | straw_hat_df_devil_fruit <- merge(straw_hat_df, straw_hat_devil_fruit) 91 | 92 | # 將結果輸出在 R Console 93 | straw_hat_df_devil_fruit 94 | ``` 95 | 96 | *** =sct 97 | ```{r} 98 | msg = "確認是否有使用 `merge()` 函數生成 `straw_hat_df_devil_fruit`?" 99 | test_object("straw_hat_df_devil_fruit", 100 | undefined_msg = msg, 101 | incorrect_msg = msg) 102 | 103 | msg = "確認是否有在 R Console 輸出 `straw_hat_df_devil_fruit`?" 104 | test_output_contains("straw_hat_df_devil_fruit", 105 | incorrect_msg = msg) 106 | 107 | success_msg("太棒了,觀察一下你的輸出,內部聯結只會保留兩個資料框有參照到的觀測值!") 108 | ``` 109 | 110 | --- type:NormalExercise lang:r xp:100 skills:4 key:5200a77316 111 | ## 左外部聯結 112 | 113 | 回憶前一個練習最後的輸出,我們原本的資料框有 9 個船員,但是其中只有 4 個船員是惡魔果實能力者,因此當 [`merge()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/merge) 函數沒有做其他參數設定時,預設即為**內部聯結**,輸出結果只會有兩個資料框交集的船員。 114 | 115 | 如果想要保留所有船員的資料,要在 [`merge()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/merge) 函數中額外指定參數 `all.x = TRUE` 請 R 語言將第一個資料框的所有觀測值都保留下來: 116 | 117 | ```{r} 118 | merge(df1, df2, all.x = TRUE) 119 | ``` 120 | 121 | 輸出的結果會保留第一個資料框中的所有觀測值,而參照不到惡魔果實的船員會以遺漏值記錄,這就是俗稱的**左外部聯結**! 122 | 123 | *** =instructions 124 | - 使用 `merge()` 函數將 `straw_hat_df` 與 `straw_hat_devil_fruit` 進行左外部聯結,將聯結後資料框宣告為 `straw_hat_df_devil_fruit`。 125 | - 將 `straw_hat_df_devil_fruit` 輸出在 R Console。 126 | 127 | *** =hint 128 | - `merge()` 函數要設定 `all.x = TRUE`。 129 | 130 | *** =pre_exercise_code 131 | ```{r} 132 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 133 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_devil_fruit.RData")) 134 | ``` 135 | 136 | *** =sample_code 137 | ```{r} 138 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 139 | 140 | # 左外部聯結 141 | straw_hat_df_devil_fruit <- 142 | 143 | # 將結果輸出在 R Console 144 | 145 | ``` 146 | 147 | *** =solution 148 | ```{r} 149 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 150 | 151 | # 左外部聯結 152 | straw_hat_df_devil_fruit <- merge(straw_hat_df, straw_hat_devil_fruit, all.x = TRUE) 153 | 154 | # 將結果輸出在 R Console 155 | straw_hat_df_devil_fruit 156 | ``` 157 | 158 | *** =sct 159 | ```{r} 160 | msg = "確認是否有使用 `merge()` 函數生成左外部聯結的結果?" 161 | test_object("straw_hat_df_devil_fruit", 162 | undefined_msg = msg, 163 | incorrect_msg = msg) 164 | 165 | msg = "確認是否有將 `straw_hat_df_devil_fruit`輸出在 R Console?" 166 | test_output_contains("straw_hat_df_devil_fruit", 167 | incorrect_msg = msg) 168 | 169 | success_msg("觀察一下左外部聯結生成的結果,注意沒有參照到的觀測值會以遺漏值方式記錄!") 170 | ``` 171 | 172 | --- type:NormalExercise lang:r xp:100 skills:4 key:cf1c36b9fc 173 | ## 右外部聯結 174 | 175 | 與前一個練習相呼應,既然有保留第一個資料框所有觀測值的左外部聯結,我們一定也有保留第二個資料框所有觀測值的**右外部聯結**。想要保留所有惡魔果實能力者的資料,要在 [`merge()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/merge) 函數中額外指定參數 `all.y = TRUE` 請 R 語言將第二個資料框的所有觀測值都保留下來: 176 | 177 | ```{r} 178 | merge(df1, df2, all.y = TRUE) 179 | ``` 180 | 181 | 為了展示**右外部聯結**的效果,我們稍微修改了第一個資料框 `straw_hat_df` 留下四個船員的角色設定,兩個能力者與兩個非能力者。輸出的結果會保留第二個資料框中的所有觀測值,而參照不到主要角色設定的惡魔果實能力者欄位會以遺漏值記錄,這就是俗稱的**右外部聯結**! 182 | 183 | *** =instructions 184 | - 先將修改後的 `straw_hat_df` 輸出在 R Console 看看。 185 | - 使用 `merge()` 函數將 `straw_hat_df` 與 `straw_hat_devil_fruit` 進行右外部聯結,將聯結後資料框宣告為 `straw_hat_df_devil_fruit`。 186 | - 將 `straw_hat_df_devil_fruit` 輸出在 R Console。 187 | 188 | *** =hint 189 | - `merge()` 函數要設定 `all.y = TRUE`。 190 | 191 | *** =pre_exercise_code 192 | ```{r} 193 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 194 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_devil_fruit.RData")) 195 | straw_hat_df <- straw_hat_df[c(1:3, 6), ] 196 | ``` 197 | 198 | *** =sample_code 199 | ```{r} 200 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 201 | 202 | # 將 straw_hat_df 輸出在 R Console 203 | 204 | 205 | # 右外部聯結 206 | straw_hat_df_devil_fruit <- 207 | 208 | # 將結果輸出在 R Console 209 | 210 | ``` 211 | 212 | *** =solution 213 | ```{r} 214 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 215 | 216 | # 將 straw_hat_df 輸出在 R Console 217 | straw_hat_df 218 | 219 | # 右外部聯結 220 | straw_hat_df_devil_fruit <- merge(straw_hat_df, straw_hat_devil_fruit, all.y = TRUE) 221 | 222 | # 將結果輸出在 R Console 223 | straw_hat_df_devil_fruit 224 | ``` 225 | 226 | *** =sct 227 | ```{r} 228 | msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?" 229 | test_output_contains("straw_hat_df", 230 | incorrect_msg = msg) 231 | 232 | msg = "確認是否有使用 `merge()` 函數進行右外部聯結?" 233 | test_object("straw_hat_df_devil_fruit", 234 | undefined_msg = msg, 235 | incorrect_msg = msg) 236 | 237 | msg = "確認是否有將 `straw_hat_df_devil_fruit` 輸出在 R Console?" 238 | test_output_contains("straw_hat_df_devil_fruit", 239 | incorrect_msg = msg) 240 | 241 | success_msg("太棒了,還差一個練習你的資料框聯結技能就可以被點滿了!") 242 | ``` 243 | 244 | --- type:NormalExercise lang:r xp:100 skills:4 key:69321d3583 245 | ## 全外部聯結 246 | 247 | 既然有保留第一個資料框所有觀測值的左外部聯結,亦有保留第二個資料框所有觀測值的右外部聯結,聰明如你一定想到我們必定有保留兩個資料框所有觀測值的聯結,你的推測沒有錯,那就是俗稱的**全外部聯結**,在 [`merge()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/merge) 函數中額外指定參數 `all.x = TRUE` 以及 `all.y = TRUE` 請 R 語言將兩個資料框的所有觀測值都保留下來: 248 | 249 | ```{r} 250 | merge(df1, df2, all.x = TRUE, all.y = TRUE) 251 | ``` 252 | 253 | *** =instructions 254 | - 先將修改後的 `straw_hat_df` 輸出在 R Console 看看。 255 | - 使用 `merge()` 函數將 `straw_hat_df` 與 `straw_hat_devil_fruit` 進行全外部聯結,將聯結後資料框宣告為 `straw_hat_df_devil_fruit`。 256 | - 將 `straw_hat_df_devil_fruit` 輸出在 R Console。 257 | 258 | *** =hint 259 | - `merge()` 函數要設定 `all.x = TRUE, all.y = TRUE`。 260 | 261 | *** =pre_exercise_code 262 | ```{r} 263 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 264 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_devil_fruit.RData")) 265 | straw_hat_df <- straw_hat_df[c(1:3, 6), ] 266 | ``` 267 | 268 | *** =sample_code 269 | ```{r} 270 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 271 | 272 | # 將 straw_hat_df 輸出在 R Console 273 | straw_hat_df 274 | 275 | # 全外部聯結 276 | straw_hat_df_devil_fruit <- 277 | 278 | # 將結果輸出在 R Console 279 | straw_hat_df_devil_fruit 280 | ``` 281 | 282 | *** =solution 283 | ```{r} 284 | # straw_hat_df 與 straw_hat_devil_fruit 已預先載入 285 | 286 | # 將 straw_hat_df 輸出在 R Console 287 | straw_hat_df 288 | 289 | # 全外部聯結 290 | straw_hat_df_devil_fruit <- merge(straw_hat_df, straw_hat_devil_fruit, all.x = TRUE, all.y = TRUE) 291 | 292 | # 將結果輸出在 R Console 293 | straw_hat_df_devil_fruit 294 | ``` 295 | 296 | *** =sct 297 | ```{r} 298 | msg = "確認你是否有將 `straw_hat_df` 輸出在 R Console?" 299 | test_output_contains("straw_hat_df", 300 | incorrect_msg = msg) 301 | 302 | msg = "確認是否有使用 `merge()` 函數進行右外部聯結?" 303 | test_object("straw_hat_df_devil_fruit", 304 | undefined_msg = msg, 305 | incorrect_msg = msg) 306 | 307 | msg = "確認你是否有將 `straw_hat_df_devil_fruit` 輸出在 R Console?" 308 | test_output_contains("straw_hat_df_devil_fruit", 309 | incorrect_msg = msg) 310 | success_msg("恭喜你,你已經成為資料聯結的高手,查一下海軍的資料庫,你已經被列入上億賞金的重點通緝名單!") 311 | ``` 312 | 313 | --- type:NormalExercise lang:r xp:100 skills:4 key:65494f3253 314 | ## 多個參照欄位 315 | 316 | 你的懸賞金額現在已經跟草帽魯夫並駕齊驅了,但你很好奇草帽魯夫的歷史懸賞金額,於是你再度駭入海軍的機密資料庫,你找到了一個資料框紀錄草帽魯夫各時期的懸賞金額。你發現了海軍利用事件以及賞金兩個欄位紀錄不同時期的懸賞金額,因此我們如果要參照不只一個欄位時,在 `by = ` 的參數設定要使用 `c()` 將多個參照欄位寫入: 317 | 318 | ```{r} 319 | merge(df1, df2, by = c("col1", "col2", ...)) 320 | ``` 321 | 322 | 資料來源:[One Piece Wiki](http://onepiece.wikia.com/wiki/Main_Page) 323 | 324 | *** =instructions 325 | - 將 `luffy_event` 與 `luffy_event_bounty` 輸出在 R Console 看看。 326 | - 將 `luffy_event` 與 `luffy_event_bounty` 內部聯結產出 `luffy_bounty`。 327 | - 將 `luffy_bounty` 輸出在 R Console 看看。 328 | 329 | *** =hint 330 | - `merge()` 函數要設定 `by = c("name", "event")` 或採預設不指定 `by = ` 亦可。 331 | 332 | *** =pre_exercise_code 333 | ```{r} 334 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/luffy_event_bounty.RData")) 335 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/luffy_event.RData")) 336 | ``` 337 | 338 | *** =sample_code 339 | ```{r} 340 | # luffy_event_bounty 與 luffy_event 都已預先載入 341 | 342 | # 將 luffy_event_bounty 與 luffy_event 輸出在 R Console 343 | 344 | 345 | 346 | # 內部聯結 347 | luffy_bounty <- 348 | 349 | # 將 luffy_bounty 輸出在 R Console 350 | 351 | ``` 352 | 353 | *** =solution 354 | ```{r} 355 | # luffy_event_bounty 與 luffy_event 都已預先載入 356 | 357 | # 將 luffy_event_bounty 與 luffy_event 輸出在 R Console 358 | luffy_event_bounty 359 | luffy_event 360 | 361 | # 內部聯結 362 | luffy_bounty <- merge(luffy_event, luffy_event_bounty, by = c("name", "event")) 363 | 364 | # 將 luffy_bounty 輸出在 R Console 365 | luffy_bounty 366 | ``` 367 | 368 | *** =sct 369 | ```{r} 370 | msg = "確認是否有輸出 `luffy_event_bounty` 在 R Console?" 371 | test_output_contains("luffy_event_bounty", 372 | incorrect_msg = msg) 373 | 374 | msg = "確認是否有輸出 `luffy_event` 在 R Console?" 375 | test_output_contains("luffy_event", 376 | incorrect_msg = msg) 377 | 378 | msg = "確認是否有使用 `merge()` 函數生成 `luffy_bounty`?" 379 | test_object("luffy_bounty", 380 | undefined_msg = msg, 381 | incorrect_msg = msg) 382 | 383 | msg = "確認是否有輸出 `luffy_bounty` 在 R Console?" 384 | test_output_contains("luffy_bounty", 385 | incorrect_msg = msg) 386 | 387 | success_msg("恭喜你!你高超的資料框整理技巧已經被海軍列為重點通緝海賊,你的名號已經傳遍了新世界,一場爭奪 One Piece 的海上冒險故事!") 388 | ``` 389 | 390 | -------------------------------------------------------------------------------- /chapter4.md: -------------------------------------------------------------------------------- 1 | --- 2 | title_meta : 第四章 3 | title : 欄位聚合與資料轉置 4 | description : 分析資料框常需要對某些欄位進行摘要統計,可能是求取總和或者平均值,讓你對變數的分佈更為清楚;有時候甚至你需要依據某個類別變數,分別計算不同類別的摘要統計,一如你在 Excel 中使用樞紐分析表一般;有經驗的資料科學家還必須熟悉長資料框與寬資料框的互相轉換,視需求靈活調整資料結構。我們將在本章節學習這些技巧與概念,一場爭奪 One Piece 的海上冒險故事! 5 | 6 | --- type:NormalExercise lang:r xp:100 skills:4 key:eb29a9a1a9 7 | ## 摘要統計 8 | 9 | 你與草帽海賊團同樣屬於**超新星世代**,知己知彼,百戰不殆。你打算要針對這個潛在對手好好分析,在第一章中我們曾經有介紹過 [`summary()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/summary) 函數,它可以幫助你快速暸解資料框的摘要,而[`summary()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/summary) 函數除了可以應用在整個資料框之外,其實也可以使用在單一的變數上: 10 | 11 | ```{r} 12 | summary(df$col) 13 | ``` 14 | 15 | 我們也可以善用簡單的 [`sum()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/sum) 函數或 [`sd()`](http://www.rdocumentation.org/packages/stats/versions/3.3.1/topics/sd) 函數產出統計值,不一定只能仰賴 [`summary()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/summary) 函數產出既定的摘要統計值。 16 | 17 | *** =instructions 18 | - 對草帽海賊團資料框使用 `summary()` 函數 19 | - 對草帽海賊團資料框之中的 `height` 變數使用 `summary()` 函數 20 | - 對草帽海賊團資料框之中的 `bounty` 變數使用 `sum()` 函數 21 | - 對草帽海賊團資料框之中的 `bounty` 變數使用 `sd()` 函數 22 | 23 | *** =hint 24 | - 將 `straw_hat_df` 作為 `summary()` 函數的唯一參數。 25 | - 將 `straw_hat_df$height` 作為 `summary()` 函數的唯一參數。 26 | - 將 `straw_hat_df$bounty` 作為 `sum()` 函數的唯一參數。 27 | - 將 `straw_hat_df$bounty` 作為 `sd()` 函數的唯一參數。 28 | 29 | *** =pre_exercise_code 30 | ```{r} 31 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 32 | ``` 33 | 34 | *** =sample_code 35 | ```{r} 36 | # straw_hat_df 已預先載入 37 | 38 | # 對 straw_hat_df 使用 summary() 39 | 40 | 41 | # 對 straw_hat_df$height 使用 summary() 42 | 43 | 44 | # 對 straw_hat_df$bounty 使用 sum() 45 | 46 | 47 | # 對 straw_hat_df$bounty 使用 sd() 48 | 49 | 50 | ``` 51 | 52 | 53 | *** =solution 54 | ```{r} 55 | # straw_hat_df 已預先載入 56 | 57 | # 對 straw_hat_df 使用 summary() 58 | summary(straw_hat_df) 59 | 60 | # 對 straw_hat_df$height 使用 summary() 61 | summary(straw_hat_df$height) 62 | 63 | # 對 straw_hat_df$bounty 使用 sum() 64 | sum(straw_hat_df$bounty) 65 | 66 | # 對 straw_hat_df$bounty 使用 sd() 67 | sd(straw_hat_df$bounty) 68 | 69 | ``` 70 | 71 | *** =sct 72 | ```{r} 73 | msg = "確認是否有對 `straw_hat_df` 使用 `summary()` 函數?" 74 | test_output_contains("summary(straw_hat_df)", 75 | incorrect_msg = msg) 76 | 77 | msg = "確認是否有對 `straw_hat_df$height` 使用 `summary()` 函數?" 78 | test_output_contains("summary(straw_hat_df$height)", 79 | incorrect_msg = msg) 80 | 81 | msg = "確認是否有對 `straw_hat_df$bounty` 使用 `sum()` 函數?" 82 | test_output_contains("sum(straw_hat_df$bounty)", 83 | incorrect_msg = msg) 84 | 85 | msg = "確認是否有對 `straw_hat_df$bounty` 使用 `sd()` 函數?" 86 | test_output_contains("sd(straw_hat_df$bounty)", 87 | incorrect_msg = msg) 88 | 89 | success_msg("看到草帽海賊團全團的懸賞金額這麼高,你有沒有覺得還是不要招惹他們好了呢?") 90 | ``` 91 | 92 | --- type:NormalExercise lang:r xp:100 skills:4 key:077f2d637a 93 | ## 摘要統計(2) 94 | 95 | 身為**超新星世代**的一員,你對草帽海賊團的戰力分析絕對不僅止於世界政府那粗糙的整體摘要統計,你想著也許針對不同性別或者不同戰鬥位置的船員分開剖析,可以幫助你找到草帽海賊團的弱點,便於在將來正面對決時能加以利用。 96 | 97 | 於是我們要來學習使用類似在 Excel 中常用的**樞紐分析表**來達成這件事情,為了簡單地做到這件事情,接下來我們要使用 [`ddply()`](http://www.rdocumentation.org/packages/plyr/versions/1.8.4/topics/ddply) 函數,跟我們先前使用的函數不一樣的地方在於,它不是 R 語言的原生函數,而是源自於一個套件 [`plyr`](http://www.rdocumentation.org/packages/plyr/versions/1.8.4),因此在使用之前必須要使用 [`library()`](http://www.rdocumentation.org/packages/SIM/versions/1.42.0/topics/Library) 函數將 [`plyr`](http://www.rdocumentation.org/packages/plyr/versions/1.8.4) 套件載入才行。 98 | 99 | ```{r} 100 | library(plyr) 101 | ``` 102 | 103 | [`ddply()`](http://www.rdocumentation.org/packages/plyr/versions/1.8.4/topics/ddply) 函數需要輸入較多參數,`.variables =` 要放的是欲分別摘要的類別型變數,`.fun = summarise` 在現階段先不做更動,後面則是加上聚合計算欄位的名稱與算式: 104 | 105 | ```{r} 106 | ddply(df, .variables = c("category1", "category2", ...), .fun = summarise, mean_value1 = mean(value)) 107 | ``` 108 | 109 | *** =instructions 110 | - 使用 `head()` 函數看一下草帽海賊團資料框 111 | - 依據性別 `gender` 計算各性別的平均身高 112 | - 依據戰鬥角色 `battle_role` 計算各角色的加總賞金 113 | - 依據性別與戰鬥角色,計算平均身高與加總賞金 114 | 115 | *** =hint 116 | - 輸入 `head(straw_hat_df)` 看看資料框 117 | - `.variables = ` 參數要指定為 `"gender"`,聚合計算可以參考 `avg_height = mean(height)` 118 | - `.variables = ` 參數要指定為 `"battle_role"`,聚合計算可以參考 `ttl_bounty = sum(bounty)` 119 | - `.variables = ` 參數要指定為 `c("gender", "battle_role")`,聚合計算可以參考 `avg_height = mean(height), ttl_bounty = sum(bounty)` 120 | 121 | *** =pre_exercise_code 122 | ```{r} 123 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 124 | battle_role <- factor(c("Fighter", "Fighter", "Support", "Support", "Fighter", "Support", "Support", "Fighter", "Fighter")) 125 | straw_hat_df$battle_role <- battle_role 126 | ``` 127 | 128 | *** =sample_code 129 | ```{r} 130 | # straw_hat_df 已預先載入 131 | 132 | # 用 head() 函數看一下 straw_hat_df 133 | 134 | 135 | # 載入 plyr 套件 136 | library(plyr) 137 | 138 | # 依據 gender 計算平均身高 139 | ddply(straw_hat_df, .variables = "__", .fun = summarise, avg_height = mean(__)) 140 | 141 | # 依據 battle_role 計算加總賞金 142 | ddply(straw_hat_df, .variables = "__", .fun = summarise, ttl_bounty = sum(__)) 143 | 144 | # 依據 gender 與 battle_role 計算平均身高與加總賞金 145 | ddply(straw_hat_df, .variables = c("__", "__"), .fun = summarise, avg_height = mean(__), ttl_bounty = sum(__)) 146 | ``` 147 | 148 | *** =solution 149 | ```{r} 150 | # straw_hat_df 已預先載入 151 | 152 | # 用 head() 函數看一下 straw_hat_df 153 | head(straw_hat_df) 154 | 155 | # 載入 plyr 套件 156 | library(plyr) 157 | 158 | # 依據 gender 計算平均身高 159 | ddply(straw_hat_df, .variables = "gender", .fun = summarise, avg_height = mean(height)) 160 | 161 | # 依據 battle_role 計算加總賞金 162 | ddply(straw_hat_df, .variables = "battle_role", .fun = summarise, ttl_bounty = sum(bounty)) 163 | 164 | # 依據 gender 與 battle_role 計算平均身高與加總賞金 165 | ddply(straw_hat_df, .variables = c("gender", "battle_role"), .fun = summarise, avg_height = mean(height), ttl_bounty = sum(bounty)) 166 | ``` 167 | 168 | *** =sct 169 | ```{r} 170 | msg = "確認你是否使用 `head()` 函數看看 `straw_hat_df` 的前六列?" 171 | test_output_contains("head(straw_hat_df)", 172 | incorrect_msg = msg) 173 | 174 | msg = "確認你是否有正確使用 `ddply()` 函數依據 `gender` 計算各性別的平均身高?" 175 | test_output_contains("ddply(straw_hat_df, .variables = \"gender\", .fun = summarise, avg_height = mean(height))", 176 | incorrect_msg = msg) 177 | 178 | msg = "確認你是否有正確使用 `ddply()` 函數依據 `battle_role` 計算各戰鬥角色的加總賞金?" 179 | test_output_contains("ddply(straw_hat_df, .variables = \"battle_role\", .fun = summarise, ttl_bounty = sum(bounty))", 180 | incorrect_msg = msg) 181 | 182 | msg = "確認你是否有正確使用 `ddply()` 函數依據 `gender` 與 `battle_role` 計算平均身高與加總賞金?" 183 | test_output_contains("ddply(straw_hat_df, .variables = c(\"gender\", \"battle_role\"), .fun = summarise, avg_height = mean(height), ttl_bounty = sum(bounty))", 184 | incorrect_msg = msg) 185 | 186 | success_msg("哇,能夠完成到這裡真的很不簡單!有這樣的實力我相信你真的是超新星世代的其中一員。我們僅僅介紹了 `plyr` 套件中的一個 `ddply()` 函數,它裡頭很有很多值得你花時間去研究的函數!") 187 | ``` 188 | 189 | --- type:NormalExercise lang:r xp:100 skills:4 key:c3028a5601 190 | ## 資料轉置:寬變長 191 | 192 | 課程進行到這裡,你的資料整理懸賞金額大概已經由數百元貝里提高到了數百萬貝里,但是要成為一個夠資格與草帽海賊團相抗衡的海賊,你的懸賞金額可得提高到數千萬貝里才行!接下來我們要學習的是關於資料的轉置,學會這個技巧之後可以提升你的資料整理懸賞金額至數千萬貝里! 193 | 194 | 我們首先介紹如何將一個寬資料框變為長資料框,你記得在草帽海賊團資料框中,我們有 2 個整數欄位嗎?它們分別是 `age` 和 `height`,但你有想過這是我們儲存資料的唯一方法嗎?我們可以改用一個類別欄位儲存數值的種類以及一個數值欄位儲存數值,如此一來不管有多少個數值,我們都可以用兩個欄位儲存! 195 | 196 | *** =instructions 197 | - 建立一個新的資料框 `straw_hat_wide_df` 僅包含姓名、年齡與身高這三個欄位。 198 | 199 | *** =hint 200 | - 可以使用 `[, c("name", "age", "height")]` 將欄位選出來。 201 | 202 | *** =pre_exercise_code 203 | ```{r} 204 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 205 | ``` 206 | 207 | *** =sample_code 208 | ```{r} 209 | # straw_hat_df 已預先載入 210 | 211 | # 建立一個新的資料框 straw_hat_wide_df 僅包含姓名、年齡與身高 212 | straw_hat_wide_df <- 213 | ``` 214 | 215 | *** =solution 216 | ```{r} 217 | # straw_hat_df 已預先載入 218 | 219 | # 建立一個新的資料框 straw_hat_wide_df 僅包含姓名、年齡與身高 220 | straw_hat_wide_df <- straw_hat_df[, c("name", "age", "height")] 221 | ``` 222 | 223 | *** =sct 224 | ```{r} 225 | msg = "確認你是否有產生 `straw_hat_wide_df` 並包含姓名、年齡與身高這三個欄位?" 226 | test_object("straw_hat_wide_df", 227 | undefined_msg = msg, 228 | incorrect_msg = msg) 229 | 230 | success_msg("好,熱身完畢了!我們把資料框簡化成三個欄位之後要開始做轉置囉!") 231 | ``` 232 | 233 | --- type:NormalExercise lang:r xp:100 skills:4 key:45945ea8ab 234 | ## 資料轉置:寬變長(2) 235 | 236 | 進行寬資料框變為長資料框時我們需要使用 [`gather()`](http://www.rdocumentation.org/packages/tidyr/versions/0.5.1/topics/gather) 函數,它不是 R 語言的原生函數,而是源自於一個套件 [`tidyr`](http://www.rdocumentation.org/packages/tidyr/versions/0.5.1)。 237 | 238 | 接著我們使用 [`gather()`](http://www.rdocumentation.org/packages/tidyr/versions/0.5.1/topics/gather) 函數來把寬資料框變為長資料框,[`gather()`](http://www.rdocumentation.org/packages/tidyr/versions/0.5.1/topics/gather) 函數必須要指定幾個參數,第一個是寬資料框名稱,而 `key = ` 是轉置後用來儲存**數值種類**的欄位名稱,`value = ` 是轉置後用來儲存**數值**的欄位名稱。後面則輸入需要被轉置的原始欄位名稱 : 239 | 240 | ```{r} 241 | gather(df_wide, key = 新命名一個變數區分數值的種類, value = 新命名一個變數存放數值, 原始數值欄位1, 原始數值欄位2, ...) 242 | ``` 243 | 244 | *** =instructions 245 | - 使用 `gather()` 函數把上一個練習生成的 `straw_hat_wide_df` 轉置為 `straw_hat_long_df`。 246 | - 把 `straw_hat_long_df` 輸出在 R Console 看看。 247 | 248 | *** =hint 249 | - `gather()` 函數的參數要指派 `straw_hat_wide_df, key = cate, value = int, height, age` 250 | 251 | *** =pre_exercise_code 252 | ```{r} 253 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 254 | straw_hat_wide_df <- straw_hat_df[, c("name", "age", "height")] 255 | library(tidyr) 256 | ``` 257 | 258 | *** =sample_code 259 | ```{r} 260 | # straw_hat_wide_df 、 tidyr 已預先載入 261 | 262 | # 轉置 263 | straw_hat_long_df <- gather(__, key = __, value = __, __, __) 264 | 265 | # 將資料框輸出在 R Console 266 | 267 | ``` 268 | 269 | *** =solution 270 | ```{r} 271 | # straw_hat_wide_df 、 tidyr 已預先載入 272 | 273 | # 轉置 274 | straw_hat_long_df <- gather(straw_hat_wide_df, key = cate, value = int, height, age) 275 | 276 | # 將資料框輸出在 R Console 277 | straw_hat_long_df 278 | ``` 279 | 280 | *** =sct 281 | ```{r} 282 | msg = "確認是否有使用 `gather()` 函數將寬資料框轉換成長資料框 `straw_hat_long_df`?" 283 | test_function("gather", 284 | args = NULL, index = 1, 285 | eval = TRUE, 286 | eq_condition = "equivalent", 287 | not_called_msg = msg, 288 | args_not_specified_msg = msg, 289 | incorrect_msg = msg) 290 | 291 | msg = "確認是否有將 `straw_hat_long_df` 輸出在 R Console?" 292 | test_output_contains("straw_hat_long_df", 293 | incorrect_msg = msg) 294 | 295 | success_msg("太棒了,我們已經學會了寬資料框變長資料框,接著來學怎麼把長資料框變成寬資料框!") 296 | ``` 297 | 298 | --- type:NormalExercise lang:r xp:100 skills:4 key:3c9b7efd39 299 | ## 資料轉置:長變寬 300 | 301 | 完成這個練習你的資料整理懸賞金額就可以提升至數千萬貝里,成為名副其實能夠跟草帽海賊團相抗衡的**超新星世代**! 302 | 303 | 進行長資料框轉置為寬資料框時我們使用同樣源於 [`tidyr`](http://www.rdocumentation.org/packages/tidyr/versions/0.5.1) 套件的 304 | [`spread()`](http://www.rdocumentation.org/packages/tidyr/versions/0.5.1/topics/spread) 函數。函數必須要指定幾個參數,第一個是長資料框名稱,而 `key = ` 是用來儲存**數值種類**的欄位名稱,`value = ` 是用來儲存**數值**的欄位名稱: 305 | 306 | ```{r} 307 | spread(df_long, key = 類別欄位, value = 數值欄位) 308 | ``` 309 | 310 | *** =instructions 311 | - 把 `straw_hat_long_df` 輸出在 R Console 看看。 312 | - 使用 `spread()` 函數把上一個練習生成的 `straw_hat_long_df` 轉置為 `straw_hat_wide_df`。 313 | - 把 `straw_hat_wide_df` 輸出在 R Console 看看。 314 | 315 | *** =hint 316 | - `spread()` 函數的參數要指派 `straw_hat_wide_df, key = cate, value = int` 317 | 318 | *** =pre_exercise_code 319 | ```{r} 320 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 321 | library(tidyr) 322 | straw_hat_wide_df <- straw_hat_df[, c("name", "age", "height")] 323 | straw_hat_long_df <- gather(straw_hat_wide_df, key = cate, value = int, height, age) 324 | ``` 325 | 326 | *** =sample_code 327 | ```{r} 328 | # straw_hat_long_df 、 tidyr 已預先載入 329 | 330 | # 將 straw_hat_long_df 輸出在 R Console看看 331 | 332 | 333 | # 轉置 334 | straw_hat_wide_df <- spread(__, key = __, value = __) 335 | 336 | # 將 straw_hat_wide_df 輸出在 R Console看看 337 | 338 | ``` 339 | 340 | *** =solution 341 | ```{r} 342 | # straw_hat_long_df 、 tidyr 已預先載入 343 | 344 | # 將 straw_hat_long_df 輸出在 R Console看看 345 | straw_hat_long_df 346 | 347 | # 轉置 348 | straw_hat_wide_df <- spread(straw_hat_long_df, key = cate, value = int) 349 | 350 | # 將 straw_hat_wide_df 輸出在 R Console看看 351 | straw_hat_wide_df 352 | ``` 353 | 354 | *** =sct 355 | ```{r} 356 | msg = "確認是否有將 `straw_hat_long_df` 輸出在 R Console?" 357 | test_output_contains("straw_hat_long_df", 358 | incorrect_msg = msg) 359 | 360 | msg = "確認是否有使用 `spread()` 函數將寬資料框轉換成長資料框 `straw_hat_wide_df`?" 361 | test_function("spread", 362 | args = NULL, index = 1, 363 | eval = TRUE, 364 | eq_condition = "equivalent", 365 | not_called_msg = msg, 366 | args_not_specified_msg = msg, 367 | incorrect_msg = msg) 368 | 369 | test_object("straw_hat_wide_df", 370 | undefined_msg = msg, 371 | incorrect_msg = msg) 372 | 373 | msg = "確認是否有將 `straw_hat_wide_df` 輸出在 R Console?" 374 | test_output_contains("straw_hat_wide_df", 375 | incorrect_msg = msg) 376 | 377 | success_msg("恭喜,你的懸賞金額已經達到數千萬貝里了!接下來你要航行到最後一座島嶼,通過試煉之後你將成為懸賞金額數億貝里,讓海軍頭痛的超級海賊!") 378 | ``` -------------------------------------------------------------------------------- /chapter2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title_meta : 第二章 3 | title : 欄與列的相關技巧 4 | description : 實務上我們很常會有新增變數、刪除變數或者篩選觀測值 ... 等的需求,在資料框的結構中,其實就是針對欄或者列進行整理,我們將在本章節學習這些技巧與概念,一場爭奪 One Piece 的海上冒險故事! 5 | 6 | --- type:NormalExercise lang:r xp:100 skills:4 key:297843af96 7 | ## 新增欄位 8 | 9 | 草帽海賊團的廚師賓什莫克·香吉士要為船員們準備餐點,卻發現主要角色設定遺漏了大家最喜愛的料理,於是他向可愛的讀者求助,就讓我們來幫助他將最喜愛的料理 `favorite_food` 加入 `straw_hat_df` 中。 10 | 11 | 資料來源:[One Piece Wiki](http://onepiece.wikia.com/wiki/Main_Page) 12 | 13 | *** =instructions 14 | - 將右邊編輯區已經定義好的 `favorite_food` 向量加入 `straw_hat_df` 中。 15 | - 把 `straw_hat_df` 輸出在 R Console 看看。 16 | 17 | *** =hint 18 | - 在編輯區輸入 `straw_hat_df$favorite_food <- favorite_food`。 19 | - 在編輯區輸入 `straw_hat_df`。 20 | 21 | *** =pre_exercise_code 22 | ```{r} 23 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 24 | ``` 25 | 26 | *** =sample_code 27 | ```{r} 28 | # 最喜愛料理的向量 29 | favorite_food <- c("Meat", "Food matches wine", "Orange", "Fish", "Food matches black tea", "Sweets", "Food matches coffee", "Food matches coke", "Milk") 30 | 31 | # 將向量加入資料框中成為新的欄位 32 | straw_hat_df$favorite_food <- 33 | 34 | # 將資料框輸出在 R Console 35 | 36 | ``` 37 | 38 | *** =solution 39 | ```{r} 40 | # 最喜愛料理的向量 41 | favorite_food <- c("Meat", "Food matches wine", "Orange", "Fish", "Food matches black tea", "Sweets", "Food matches coffee", "Food matches coke", "Milk") 42 | 43 | # 將向量加入資料框中成為新的欄位 44 | straw_hat_df$favorite_food <- favorite_food 45 | 46 | # 將資料框輸出在 R Console 47 | straw_hat_df 48 | ``` 49 | 50 | *** =sct 51 | ```{r} 52 | msg = "不需要刪除原本幫你定義好的向量!" 53 | test_object("favorite_food", 54 | undefined_msg = msg, 55 | incorrect_msg = msg) 56 | 57 | msg = "確認是否有將最喜愛料理的向量加入資料框中成為新的欄位?" 58 | test_data_frame("straw_hat_df", 59 | columns = "favorite_food", 60 | eq_condition = "equivalent", 61 | undefined_msg = msg, 62 | undefined_cols_msg = msg, 63 | incorrect_msg = msg) 64 | 65 | test_output_contains("straw_hat_df", 66 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 67 | 68 | success_msg("你幫了香吉士一個大忙,這樣他才知道該準備哪些料理給船員們吃,佳魯丘 <3") 69 | ``` 70 | 71 | --- type:NormalExercise lang:r xp:100 skills:4 key:142b366f49 72 | ## 新增欄位(2) 73 | 74 | R 語言有一個很可愛的特性是**殊途同歸**,做同樣一件事情,可能有多種方式可以達成。在這個練習中我們要介紹如何使用 [`cbind()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/cbind) 函數來將最喜愛的料理 `favorite_food` 加入 `straw_hat_df` 中。 75 | 76 | ```{r} 77 | df <- cbind(df, column_to_add) 78 | ``` 79 | 80 | *** =instructions 81 | - 將右邊編輯區已經定義好的 `favorite_food` 向量利用 `cbind()` 函數加入 `straw_hat_df` 中。 82 | - 把 `straw_hat_df` 輸出在 R Console 看看。 83 | 84 | *** =hint 85 | - 在編輯區輸入 `straw_hat_df <- cbind(straw_hat_df, favorite_food)`。 86 | - 在編輯區輸入 `straw_hat_df`。 87 | 88 | *** =pre_exercise_code 89 | ```{r} 90 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 91 | ``` 92 | 93 | *** =sample_code 94 | ```{r} 95 | # 最喜愛料理的向量 96 | favorite_food <- c("Meat", "Food matches wine", "Orange", "Fish", "Food matches black tea", "Sweets", "Food matches coffee", "Food matches coke", "Milk") 97 | 98 | # 利用 cbind() 函數將向量加入資料框中成為新的欄位 99 | straw_hat_df <- 100 | 101 | # 將資料框輸出在 R Console 102 | 103 | ``` 104 | 105 | *** =solution 106 | ```{r} 107 | # 最喜愛料理的向量 108 | favorite_food <- c("Meat", "Food matches wine", "Orange", "Fish", "Food matches black tea", "Sweets", "Food matches coffee", "Food matches coke", "Milk") 109 | 110 | # 利用 cbind() 函數將向量加入資料框中成為新的欄位 111 | straw_hat_df <- cbind(straw_hat_df, favorite_food) 112 | 113 | # 將資料框輸出在 R Console 114 | straw_hat_df 115 | ``` 116 | 117 | *** =sct 118 | ```{r} 119 | msg = "不需要刪除原本幫你定義好的向量!" 120 | test_object("favorite_food", 121 | undefined_msg = msg, 122 | incorrect_msg = msg) 123 | 124 | msg = "確認是否有使用 `cbind()` 函數?" 125 | test_function("cbind", 126 | args = NULL, index = 1, 127 | eval = TRUE, 128 | eq_condition = "equivalent", 129 | not_called_msg = msg, 130 | args_not_specified_msg = NULL, 131 | incorrect_msg = msg) 132 | 133 | msg = "確認是否有將最喜愛料理的向量加入資料框中成為新的欄位?" 134 | test_data_frame("straw_hat_df", 135 | columns = "favorite_food", 136 | eq_condition = "equivalent", 137 | undefined_msg = msg, 138 | undefined_cols_msg = msg, 139 | incorrect_msg = msg) 140 | 141 | test_output_contains("straw_hat_df", 142 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 143 | 144 | success_msg("太棒了,學會新增之後我們來學習如何刪除!") 145 | ``` 146 | 147 | --- type:NormalExercise lang:r xp:100 skills:4 key:c8c237a023 148 | ## 刪除欄位 149 | 150 | 你在前一個練習中已經幫賓什莫克·香吉士解決了問題,你突然又覺得最喜愛的料理這個資訊無關痛癢。這樣子確實十分地善變,但是現實生活中你的主管或你的同事很可能也是如此的善變呢!讓我們將最喜愛的料理 `favorite_food` 從 `straw_hat_df` 中移除,在 R 語言中要將資料框中的欄位移除非常容易,只需要把該欄位指派為 `NULL` 即可: 151 | 152 | ```{r} 153 | df$column_to_delete <- NULL 154 | ``` 155 | 156 | *** =instructions 157 | - 將 `straw_hat_df$favorite_food` 欄位從 `straw_hat_df` 中移除。 158 | - 把 `straw_hat_df` 輸出在 R Console 看看。 159 | 160 | *** =hint 161 | - 在編輯區輸入 `straw_hat_df$favorite_food <- NULL`。 162 | - 在編輯區輸入 `straw_hat_df`。 163 | 164 | *** =pre_exercise_code 165 | ```{r} 166 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 167 | favorite_food <- c("Meat", "Food matches wine", "Orange", "Fish", "Food matches black tea", "Sweets", "Food matches coffee", "Food matches coke", "Milk") 168 | straw_hat_df$favorite_food <- favorite_food 169 | ``` 170 | 171 | *** =sample_code 172 | ```{r} 173 | # 刪除最喜愛料理的欄位 174 | 175 | 176 | # 將資料框輸出在 R Console 177 | 178 | ``` 179 | 180 | *** =solution 181 | ```{r} 182 | # 刪除最喜愛料理的欄位 183 | straw_hat_df$favorite_food <- NULL 184 | 185 | # 將資料框輸出在 R Console 186 | straw_hat_df 187 | ``` 188 | 189 | *** =sct 190 | ```{r} 191 | msg = "確認是否有將最喜愛料理的欄位指派給 NULL?" 192 | test_object("straw_hat_df", 193 | undefined_msg = msg, 194 | incorrect_msg = msg) 195 | 196 | test_output_contains("straw_hat_df", 197 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 198 | 199 | success_msg("太好了,不管其他人多麽善變,新增刪除欄位都難不倒你了!") 200 | ``` 201 | 202 | --- type:NormalExercise lang:r xp:100 skills:4 key:c78ba59b50 203 | ## 刪除欄位(2) 204 | 205 | 還記得我們在 [R 語言導論](https://www.datacamp.com/community/open-courses/r-%E8%AA%9E%E8%A8%80%E5%B0%8E%E8%AB%96#gs.FaeP7Yg)中有提到一個便利的 [`subset()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/subset) 函數嗎?我們也可以利用它來刪除欄位,只需在想要刪除的欄位名稱前面加上**減號**,而且它還提供了更進階的功能,讓你可以一次刪除多個欄位! 206 | 207 | ```{r} 208 | df <- subset(df, select = -col1) 209 | df <- subset(df, select = c(-col1, -col2, ...)) 210 | ``` 211 | 212 | *** =instructions 213 | - 利用 `subset()` 函數寫一行程式將職業 `straw_hat_df$occupation` 與身高 `straw_hat_df$height` 從 `straw_hat_df` 中移除。 214 | - 把 `straw_hat_df` 輸出在 R Console 看看。 215 | 216 | *** =hint 217 | - 在編輯區輸入 `straw_hat_df <- subset(straw_hat_df, select = c(-occupation, -height))`。 218 | - 在編輯區輸入 `straw_hat_df`。 219 | 220 | *** =pre_exercise_code 221 | ```{r} 222 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 223 | ``` 224 | 225 | *** =sample_code 226 | ```{r} 227 | # 用 subset 函數一次刪除職業與身高兩個欄位 228 | straw_hat_df <- subset(__, select = c(-__, -__)) 229 | 230 | # 將資料框輸出在 R Console 231 | 232 | ``` 233 | 234 | *** =solution 235 | ```{r} 236 | # 用 subset 函數一次刪除職業與身高兩個欄位 237 | straw_hat_df <- subset(straw_hat_df, select = c(-occupation, -height)) 238 | 239 | # 將資料框輸出在 R Console 240 | straw_hat_df 241 | ``` 242 | 243 | *** =sct 244 | ```{r} 245 | msg = "確認是否正確地使用 `subset()` 函數?" 246 | test_function("subset", 247 | args = NULL, index = 1, 248 | eval = TRUE, 249 | eq_condition = "equivalent", 250 | not_called_msg = msg, 251 | args_not_specified_msg = NULL, 252 | incorrect_msg = msg) 253 | 254 | msg = "確認是否使用 `subset()` 函數刪除了職業與身高兩個欄位?" 255 | test_object("straw_hat_df", 256 | undefined_msg = msg, 257 | incorrect_msg = msg) 258 | 259 | test_output_contains("straw_hat_df", 260 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 261 | 262 | success_msg("太棒了,除了可以直接指定欄位的名稱,你也可以用索引值來指定,有空可以在 R Console 中練習!") 263 | ``` 264 | 265 | --- type:NormalExercise lang:r xp:100 skills:4 key:ccfe68db30 266 | ## 為欄位重新命名 267 | 268 | R 語言可以使用 [`names()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/names) 函數將資料框的「變數名稱」以向量的型態輸出: 269 | 270 | ```{r} 271 | names(df) 272 | ``` 273 | 274 | 透過指定索引值就可以對欄位重新命名: 275 | 276 | ```{r} 277 | names(df)[1] <- "new_name_column1" 278 | ``` 279 | 280 | 注意 R 語言的索引值是由 **1** 起算,這一點跟其他程式語言從 0 起算是不一樣的! 281 | 282 | *** =instructions 283 | - 將 `straw_hat_df` 的賞金欄位 `bounty` 改命名為 `reward`。 284 | - 把 `straw_hat_df` 的欄位名稱輸出在 R Console 看看。 285 | 286 | *** =hint 287 | - 在編輯區輸入 `names(straw_hat_df)[4] <- "reward"`。 288 | - 在編輯區輸入 `names(straw_hat_df)`。 289 | 290 | *** =pre_exercise_code 291 | ```{r} 292 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 293 | ``` 294 | 295 | *** =sample_code 296 | ```{r} 297 | # straw_hat_df 資料框已預先載入 298 | 299 | # 將賞金欄位 straw_hat_df$bounty 改命名為 straw_hat_df$reward 300 | 301 | # 將 straw_hat_df 的欄位名稱輸出在 R Console 302 | 303 | ``` 304 | 305 | *** =solution 306 | ```{r} 307 | # straw_hat_df 資料框已預先載入 308 | 309 | # 將賞金欄位 straw_hat_df$bounty 改命名為 straw_hat_df$reward 310 | names(straw_hat_df)[4] <- "reward" 311 | 312 | # 將 straw_hat_df 的欄位名稱輸出在 R Console 313 | names(straw_hat_df) 314 | ``` 315 | 316 | *** =sct 317 | ```{r} 318 | msg = "確認是否有使用 `names()` 函數將 bounty 欄位改命名為 reward?" 319 | test_data_frame("straw_hat_df", 320 | columns = "reward", 321 | eq_condition = "equivalent", 322 | undefined_msg = "確認是否有將 `straw_hat_df` 移除?", 323 | undefined_cols_msg = msg, 324 | incorrect_msg = msg) 325 | 326 | test_output_contains("names(straw_hat_df)", 327 | incorrect_msg = "確認是否有將 `straw_hat_df` 的欄位名稱輸出在 R Console?") 328 | 329 | success_msg("連龜毛的重新命名欄位都難不倒你,太棒了!") 330 | ``` 331 | 332 | --- type:NormalExercise lang:r xp:100 skills:4 key:d3c614f19b 333 | ## 鑽研 subset() 函數 334 | 335 | 前面練習示範的刪除欄位只是 [`subset()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/subset) 函數的其中一個功能。[`subset()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/subset) 函數在篩選觀測值與變數非常實用,假如你想快速看到草帽魯夫的懸賞金額,可以練習在 R Console 輸入: 336 | 337 | ```{r} 338 | subset(straw_hat_df, name == "Monkey D. Luffy", select = c(name, bounty)) 339 | ``` 340 | 341 | *** =instructions 342 | - 將草帽海賊團賞金大於 1000 萬貝里並且年齡小於 30 歲的成員篩選出來,欄位只需要包含姓名、賞金與年齡。 343 | 344 | *** =hint 345 | - 在編輯區輸入 `subset(straw_hat_df, bounty > 10000000 & age < 30, select = c(name, bounty, age))` 346 | 347 | *** =pre_exercise_code 348 | ```{r} 349 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 350 | ``` 351 | 352 | *** =sample_code 353 | ```{r} 354 | # straw_hat_df 資料框已預先載入 355 | 356 | # 篩選賞金大於 1000 萬貝里並且年齡小於 30 歲,欄位只需要包含姓名、賞金與年齡 357 | subset(straw_hat_df, bounty > __ & age < __, select = c(name, __, age)) 358 | ``` 359 | 360 | *** =solution 361 | ```{r} 362 | # straw_hat_df 資料框已預先載入 363 | 364 | # 篩選賞金大於 1000 萬貝里並且年齡小於 30 歲,欄位只需要包含姓名、賞金與年齡 365 | subset(straw_hat_df, bounty > 10000000 & age < 30, select = c(name, bounty, age)) 366 | ``` 367 | 368 | *** =sct 369 | ```{r} 370 | test_output_contains("subset(straw_hat_df, bounty > 10000000 & age < 30, select = c(name, bounty, age))", 371 | incorrect_msg = "確認是否有篩選出題目所要求的觀測值與欄位?") 372 | 373 | success_msg("太棒了,`subset()` 函數是強而有力的工具,它能夠讓你更有效率地處理資料框!") 374 | ``` 375 | 376 | --- type:NormalExercise lang:r xp:100 skills:4 key:2de6bd4bcf 377 | ## 新增列數 378 | 379 | 前面練習我們介紹了 [`cbind()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/subset) 函數能夠協助新增欄位,聰明的你一定能夠舉一反三,想到是不是也有相對應的函數可以協助新增列數呢?沒錯,R 語言的確有相對應的 [`rbind()`](http://www.rdocumentation.org/packages/R6Frame/versions/0.1.0/topics/rbind) 函數: 380 | 381 | ```{r} 382 | df <- rbind(df, row_to_add) 383 | ``` 384 | 385 | 鄉民們對於第十位船員的猜測議論紛紛,各種神預測,在這裡我們稍微懷舊一下,草帽海賊團永遠的夥伴:阿拉巴斯坦王國的薇薇公主。 386 | 387 | 資料來源:[One Piece Wiki](http://onepiece.wikia.com/wiki/Main_Page) 388 | 389 | *** =instructions 390 | - 利用 `rbind()` 將薇薇公主加入草帽海賊團資料框。 391 | - 把 `straw_hat_df` 輸出在 R Console 看看。 392 | 393 | *** =hint 394 | - 在編輯區輸入 `straw_hat_df <- rbind(straw_hat_df, princess_vivi)`。 395 | - 在編輯區輸入 `straw_hat_df`。 396 | 397 | *** =pre_exercise_code 398 | ```{r} 399 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 400 | ``` 401 | 402 | *** =sample_code 403 | ```{r} 404 | # straw_hat_df 資料框已預先載入 405 | 406 | # 薇薇公主 407 | princess_vivi <- c("Nefeltari Vivi", "Female", "Princess of Alabasta", NA, 18, "02-02", NA) 408 | 409 | # 將薇薇公主加入草帽海賊團資料框 410 | straw_hat_df <- 411 | 412 | # 把 straw_hat_df 輸出在 R Console 413 | 414 | ``` 415 | 416 | *** =solution 417 | ```{r} 418 | # straw_hat_df 資料框已預先載入 419 | 420 | # 薇薇公主 421 | princess_vivi <- c("Nefeltari Vivi", "Female", "Princess of Alabasta", NA, 18, "02-02", NA) 422 | 423 | # 將薇薇公主加入草帽海賊團資料框 424 | straw_hat_df <- rbind(straw_hat_df, princess_vivi) 425 | 426 | # 把 straw_hat_df 輸出在 R Console 427 | straw_hat_df 428 | ``` 429 | 430 | *** =sct 431 | ```{r} 432 | msg = "確認是否有正確使用 `rbind()` 函數?" 433 | test_function("rbind", 434 | args = NULL, index = 1, 435 | eval = TRUE, 436 | eq_condition = "equivalent", 437 | not_called_msg = msg, 438 | args_not_specified_msg = NULL, 439 | incorrect_msg = msg) 440 | 441 | msg = "確認是否有將薇薇公主加入草帽海賊團資料框?" 442 | 443 | test_object("straw_hat_df", 444 | undefined_msg = msg, 445 | incorrect_msg = msg) 446 | 447 | test_output_contains("straw_hat_df", 448 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 449 | 450 | success_msg("草帽海賊團離開阿拉巴斯坦王國時,背對著薇薇和跑得快舉起了畫在左手臂上的 X 記號。不管第十個夥伴是誰,薇薇和跑得快仍被認定是草帽海賊團的船員!") 451 | ``` -------------------------------------------------------------------------------- /chapter3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title_meta : 第三章 3 | title : 生成衍生變數 4 | description : 從資料庫查詢得到的結果或者既有資料的變數有時候並不能滿足我們的分析需求,這時我們會需要生成衍生變數,可能是將類別型變數重新歸類、將數值型變數歸類為類別型變數或者針對數值型變數作計算 ... 等,我們將在本章節學習這些技巧與概念,一場爭奪 One Piece 的海上冒險故事! 5 | 6 | --- type:NormalExercise lang:r xp:100 skills:4 key:db8d80a572 7 | ## 類別型變數的分類 8 | 9 | 雖然草帽海賊團每個船員都有獨立作戰的能力,但交戰仍然區分為兩種類型:輔助型與戰鬥型。具體而言,我們的航海士(Navigator)、狙擊手(Sniper)、船醫(Doctor)與考古學家(Archaeologist)是屬於輔助型(Support),其餘船員則不意外是屬於戰鬥型(Fighter)。我們要多加一個欄位紀錄船員們的戰鬥類型 `battle_role`,這樣的二元重新分類可以善用 [`ifelse()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/ifelse) 函數,讓我們來練習看看! 10 | 11 | ```{r} 12 | ifelse(test, yes, no) 13 | ``` 14 | 15 | 在對比文字時我們使用一個特殊的運算子符號 `%in%`,如果運算子左方的文字有出現在右方的向量中,就會回傳 `TRUE` 反之則回傳 `FALSE`。 16 | 17 | *** =instructions 18 | - 將右邊編輯區畫底線的空位填入適當值。 19 | - 把 `straw_hat_df` 輸出在 R Console 看看。 20 | 21 | *** =hint 22 | - 我們要把職業是航海士(Navigator)、狙擊手(Sniper)、船醫(Doctor)與考古學家(Archaeologist)的船員指定為 `battle_role = "Support"`,其餘指定為 `battle_role = "Fighter"`。 23 | - 在編輯區輸入 `straw_hat_df`。 24 | 25 | *** =pre_exercise_code 26 | ```{r} 27 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 28 | ``` 29 | 30 | *** =sample_code 31 | ```{r} 32 | # straw_hat_df 已預先載入 33 | 34 | # 填入適當的值 35 | straw_hat_df$battle_role <- ifelse(straw_hat_df$occupation %in% c("__", "__", "__", "__"), yes = "__", no = "__") 36 | 37 | # 將資料框輸出在 R Console 38 | 39 | ``` 40 | 41 | *** =solution 42 | ```{r} 43 | # straw_hat_df 已預先載入 44 | 45 | # 填入適當的值 46 | straw_hat_df$battle_role <- ifelse(straw_hat_df$occupation %in% c("Navigator", "Sniper", "Doctor", "Archaeologist"), yes = "Support", no = "Fighter") 47 | 48 | # 將資料框輸出在 R Console 49 | straw_hat_df 50 | ``` 51 | 52 | *** =sct 53 | ```{r} 54 | test_data_frame("straw_hat_df", columns = "battle_role", 55 | undefined_msg = "確認你是否不小心將 `straw_hat_df` 移除了?", 56 | undefined_cols_msg = "確認你是否正確生成 `battle_role` 變數?", 57 | incorrect_msg = "確認你是否正確生成 `battle_role` 變數?") 58 | 59 | test_output_contains("straw_hat_df", 60 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 61 | 62 | success_msg("太棒了,但你有想過假如我們重新歸類不只兩種類別,應該怎麼辦?") 63 | ``` 64 | 65 | --- type:NormalExercise lang:r xp:100 skills:4 key:ec549da7b3 66 | ## 類別型變數的分類(2) 67 | 68 | 在輔助型戰鬥角色中,其實可以再將狙擊手(Sniper)另外歸類為遠距攻擊型(Range),而我們的船醫(Doctor)、考古學家(Archaeologist)與航海士(Navigator)仍然歸類為輔助型(Support),原本歸類為戰鬥型(Fighter)的船長(Captain)、劍士(Swordsman)、廚師(Cook)、船匠(Shipwright)與音樂家(Musician)則維持原歸類,如此一來我們的類別會達到三種,這時我們採用向量索引值進行歸類。 69 | 70 | *** =instructions 71 | - 將右邊編輯區畫底線的空位填入適當值。 72 | - 把 `straw_hat_df` 輸出在 R Console 看看。 73 | 74 | *** =hint 75 | - 我們要把職業是狙擊手(Sniper)與的船員指定為 `battle_role = "Range"`,職業是船醫(Doctor)、考古學家(Archaeologist)與航海士(Navigator)的船員指定為 `battle_role = "Support"`,其餘指定為 `battle_role = "Fighter"`。 76 | - 在編輯區輸入 `straw_hat_df`。 77 | 78 | *** =pre_exercise_code 79 | ```{r} 80 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 81 | ``` 82 | 83 | *** =sample_code 84 | ```{r} 85 | # straw_hat_df 已預先載入 86 | 87 | # 填入適當的值 88 | straw_hat_df$battle_role[straw_hat_df$occupation == c("__")] <- "Range" 89 | straw_hat_df$battle_role[straw_hat_df$occupation %in% c("__", "__", "__")] <- "Support" 90 | straw_hat_df$battle_role[straw_hat_df$occupation %in% c("__", "__", "__", "__", "__")] <- "Fighter" 91 | 92 | # 將資料框輸出在 R Console 93 | 94 | ``` 95 | 96 | *** =solution 97 | ```{r} 98 | # straw_hat_df 已預先載入 99 | 100 | # 填入適當的值 101 | straw_hat_df$battle_role[straw_hat_df$occupation == "Sniper"] <- "Range" 102 | straw_hat_df$battle_role[straw_hat_df$occupation %in% c("Doctor", "Archaeologist", "Navigator")] <- "Support" 103 | straw_hat_df$battle_role[straw_hat_df$occupation %in% c("Captain", "Swordsman", "Cook", "Shipwright", "Musician")] <- "Fighter" 104 | 105 | # 將資料框輸出在 R Console 106 | straw_hat_df 107 | ``` 108 | 109 | *** =sct 110 | ```{r} 111 | test_data_frame("straw_hat_df", 112 | columns = "battle_role", 113 | eq_condition = "equivalent", 114 | undefined_msg = "確認你是否將 `straw_hat_df` 移除了?", 115 | undefined_cols_msg = "確認你是否有正確將 `straw_hat_df$battle_role` 作分類?", 116 | incorrect_msg = "確認你是否有正確將 `straw_hat_df$battle_role` 作分類?") 117 | 118 | test_output_contains("straw_hat_df", 119 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 120 | 121 | success_msg("太好了,接下來我們要看看怎麼對數值型變數進行分類!") 122 | ``` 123 | 124 | --- type:NormalExercise lang:r xp:100 skills:4 key:70f2080cea 125 | ## 數值型變數的分類 126 | 127 | 草帽海賊團的船員經過多雷斯羅薩決戰之後賞金大幅上升,新世界其他的海賊團無不虎視眈眈,對草帽海賊團進行戰力評估,他們想要將船員依照賞金級距切分為低、中與高三個等級,這個作法如同新增加了一個類別型變數,但卻是由既有的數值型變數所衍生得到。在 R 語言中,我們可以善用 [`cut()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/cut) 函數來做這件事情。 128 | 129 | ```{r} 130 | df$new_column <- cut(df$column, breaks = c(0, break1, break2, Inf), labels = c("label1", "label2", "label3")) 131 | ``` 132 | 133 | 其中 `breaks` 參數設定必須要有一個最小值與最大值,範例中是指介於 `0 - break1` 的數值歸類為 `label1`,介於 `break1 - break2` 的數值歸類為 `label2`,而介於 `break2 - Inf` 的數值歸類為 `label3`,`Inf` 在 R 語言中是無限大的數值,你可以在 R Console 中輸入 `class(Inf)` 來驗證。 134 | 135 | *** =instructions 136 | - 新增一個變數 `bounty_level` 將賞金小於 8 千 3 百萬貝里的船員歸類為 `"Low"`,賞金介於 8 千 3 百萬貝里與 1 億 8 千萬貝里之間的船員歸類為 `"Medium"`,將賞金高於 1 億 8 千萬貝里的船員歸類為 `"High"`。 137 | - 把 `straw_hat_df` 輸出在 R Console 看看。 138 | 139 | *** =hint 140 | - `cut()` 函數的第一個參數要設為 `straw_hat_df$bounty`,`breaks` 的級距要加入 8 千 3 百萬貝里與 1 億 8 千萬貝里,`labels` 則是要將 `"Low"`、 `"Medium"` 與 `"High"` 依序放入! 141 | - 在編輯區輸入 `straw_hat_df`。 142 | 143 | *** =pre_exercise_code 144 | ```{r} 145 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 146 | ``` 147 | 148 | *** =sample_code 149 | ```{r} 150 | # straw_hat_df 已預先載入 151 | 152 | # 填入適當的值 153 | straw_hat_df$bounty_level <- cut(straw_hat_df$bounty, breaks = c(0, __, __, Inf), labels = c("__", "__", "__")) 154 | 155 | # 將資料框輸出在 R Console 156 | 157 | ``` 158 | 159 | *** =solution 160 | ```{r} 161 | # straw_hat_df 已預先載入 162 | 163 | # 填入適當的值 164 | straw_hat_df$bounty_level <- cut(straw_hat_df$bounty, breaks = c(0, 83000000, 180000000, Inf), labels = c("Low", "Medium", "High")) 165 | 166 | # 將資料框輸出在 R Console 167 | straw_hat_df 168 | ``` 169 | 170 | *** =sct 171 | ```{r} 172 | msg = "確認是否有正確使用 `cut()` 函數?" 173 | test_function("cut", 174 | args = NULL, index = 1, 175 | eval = TRUE, 176 | eq_condition = "equivalent", 177 | not_called_msg = msg, 178 | args_not_specified_msg = NULL, 179 | incorrect_msg = msg) 180 | 181 | msg = "確認是否有將船員依照賞金分類為低中高三個級距?" 182 | test_data_frame("straw_hat_df", 183 | columns = "bounty_level", 184 | eq_condition = "equivalent", 185 | undefined_msg = "確認是否將 `straw_hat_df` 移除了?", 186 | undefined_cols_msg = msg, 187 | incorrect_msg = msg) 188 | 189 | test_output_contains("straw_hat_df", 190 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 191 | 192 | success_msg("哇,你已經對草帽海賊團的戰力瞭若指掌,但光是這樣還不足以讓你跟他們相抗衡,你還需要繼續強化戰力!") 193 | ``` 194 | 195 | --- type:NormalExercise lang:r xp:100 skills:4 key:3d3db367ea 196 | ## 衍生計算數值型變數 197 | 198 | 在前一個練習中我們對賞金進行級距的切分時你是否有感覺到單位的不便?沒錯,通常在處理較大數量級的變數時我們會轉換單位便於使用,像是千、百萬或者十億。現在就讓我們來新增一個以百萬元貝里作為單位的變數 `bounty_million`。 199 | 200 | *** =instructions 201 | - 將原本的 `straw_hat_df$bounty` 除以 1,000,000 並指派給一個新資料框變數 `straw_hat_df$bounty_million`。 202 | - 把 `straw_hat_df` 輸出在 R Console 看看。 203 | 204 | *** =hint 205 | - 在編輯區輸入 `straw_hat_df$bounty_million <- straw_hat_df$bounty / 1000000`。 206 | - 在編輯區輸入 `straw_hat_df`。 207 | 208 | *** =pre_exercise_code 209 | ```{r} 210 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 211 | ``` 212 | 213 | *** =sample_code 214 | ```{r} 215 | # straw_hat_df 已預先載入 216 | 217 | # 新增一個以百萬元貝里作為單位的 straw_hat_df$bounty_million 218 | straw_hat_df$bounty_million <- 219 | 220 | # 將資料框輸出在 R Console 221 | 222 | ``` 223 | 224 | *** =solution 225 | ```{r} 226 | # straw_hat_df 已預先載入 227 | 228 | # 新增一個以百萬元貝里作為單位的 straw_hat_df$bounty_million 229 | straw_hat_df$bounty_million <- straw_hat_df$bounty / 1000000 230 | 231 | # 將資料框輸出在 R Console 232 | straw_hat_df 233 | ``` 234 | 235 | *** =sct 236 | ```{r} 237 | msg = "確認是否有正確將賞金除以 1 百萬並產生一個新變數 `bounty_million`?" 238 | test_data_frame("straw_hat_df", 239 | columns = "bounty_million", 240 | undefined_msg = "確認是否不小心將 `straw_hat_df` 移除了?", 241 | undefined_cols_msg = msg, 242 | incorrect_msg = msg) 243 | 244 | test_output_contains("straw_hat_df", 245 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 246 | 247 | success_msg("真是太厲害了,這下衍生計算數值型變數也難不倒你了!") 248 | ``` 249 | 250 | --- type:NormalExercise lang:r xp:100 skills:4 key:324a377059 251 | ## 較難的衍生變數 252 | 253 | 前進新世界,邁向成為海賊王道路上的挑戰是愈來愈艱辛,在接下來的練習我們要處理有一點棘手的問題。在原始的角色設定中,我們只有船員們的年齡與生日的月份和日期,即便海賊王世界所使用的紀年與我們所熟稔的西元紀年迥異,身為超級粉絲與資料狂熱份子,你依然想要新增一個變數欄位來紀錄包含西元年份的草帽海賊團船員生日。 254 | 255 | 我們要先介紹 `Sys.Date()` 這個函數,它會回傳現在的系統日期,你可以在 R Console 輸入: 256 | 257 | ```{r} 258 | Sys.Date() 259 | ``` 260 | 261 | R Console 會將現在的系統日期以 "%Y-%m-%d" 的格式回傳。`%Y` 代表四位數字的西元紀年,`%m` 代表兩位數字的月份,`%d` 代表兩位數字的日期。而運用 [`format()`](http://www.rdocumentation.org/packages/utils/versions/3.3.1/topics/format) 函數可以得到我們需要的西元年。 262 | 263 | ```{r} 264 | format(Sys.Date(), '%Y') 265 | ``` 266 | 267 | 產生出來的西元年格式是字元,如果想要做運算還需要利用 [`as.numeric()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/numeric) 轉為數值。 268 | 269 | ```{r} 270 | as.numeric(format(Sys.Date(), '%Y')) 271 | ``` 272 | 273 | *** =instructions 274 | - 將 `Sys.Date()` 的產出指派給一個變數 `sys_date`。 275 | - 利用 `format()` 函數將 `sys_date` 的西元年指派給 `sys_date_year`。 276 | - 利用 `as.numeric()` 函數將 `sys_date_year` 轉換為數值並指派給 `sys_date_year_num`。 277 | 278 | *** =hint 279 | - `Sys.Date()` 不需要輸入參數。 280 | - `format()` 函數第二個參數必須指定為 `'%Y'`。 281 | 282 | *** =pre_exercise_code 283 | ```{r} 284 | # no pec 285 | ``` 286 | 287 | *** =sample_code 288 | ```{r} 289 | # 產生 sys_date 290 | sys_date <- 291 | 292 | # 產生 sys_date_year 293 | sys_date_year <- 294 | 295 | # 產生 sys_date_year_num 296 | sys_date_year_num <- 297 | 298 | # 將 sys_date 、 sys_date_year 與 sys_date_year_num 輸出在 R Console 299 | 300 | ``` 301 | 302 | *** =solution 303 | ```{r} 304 | # 產生 sys_date 305 | sys_date <- Sys.Date() 306 | 307 | # 產生 sys_date_year 308 | sys_date_year <- format(sys_date, '%Y') 309 | 310 | # 產生 sys_date_year_num 311 | sys_date_year_num <- as.numeric(sys_date_year) 312 | 313 | # 將 sys_date 、 sys_date_year 與 sys_date_year_num 輸出在 R Console 314 | sys_date 315 | sys_date_year 316 | sys_date_year_num 317 | ``` 318 | 319 | *** =sct 320 | ```{r} 321 | msg = "確認是否有正確使用 `Sys.Date()` 函數產出 `sys_date`?" 322 | test_object("sys_date", 323 | undefined_msg = msg, 324 | incorrect_msg = msg) 325 | 326 | msg = "確認是否有正確使用 `format()` 函數產出 `sys_date_year`?" 327 | test_object("sys_date_year", 328 | undefined_msg = msg, 329 | incorrect_msg = msg) 330 | 331 | msg = "確認是否有正確使用 `as.numeric()` 函數產出 `sys_date_year_num`?" 332 | test_object("sys_date_year_num", 333 | undefined_msg = msg, 334 | incorrect_msg = msg) 335 | 336 | msg = "確認是否有將 `sys_date` 、 `sys_date_year` 與 `sys_date_year_num` 輸出在 R Console?" 337 | test_output_contains("sys_date", 338 | times = 1, 339 | incorrect_msg = msg) 340 | test_output_contains("sys_date_year", 341 | times = 1, 342 | incorrect_msg = msg) 343 | test_output_contains("sys_date_year_num", 344 | times = 1, 345 | incorrect_msg = msg) 346 | 347 | success_msg("太好了,接下來我們要把產出的西元年份減去船員們的年齡,來得到每個人的西元出生年份!") 348 | ``` 349 | 350 | --- type:NormalExercise lang:r xp:100 skills:4 key:b1faadbe0c 351 | ## 較難的衍生變數(2) 352 | 353 | 在前一個練習我們已經生成被儲存為數值類型的系統日期西元年份,接下來我們要用每個船員各自的年齡來計算生日的西元年份,R 語言的使用者在產生衍生變數的過程不喜歡扛著整個資料框,於是我們會先將要使用於計算的變數獨立出來: 354 | 355 | ```{r} 356 | vector1 <- df$col1 357 | ``` 358 | 359 | 計算後我們會得到船員的生日西元年份,但是你忽然想起來 `birthday` 是儲存成字元的資料格式,於是在結合之前可別忘了使用 [`as.character()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/character) 函數轉換為字元! 360 | 361 | *** =instructions 362 | - 將年齡從資料框中選出,另外指派為一個向量 `age`。 363 | - 將生日從資料框中選出,另外指派為一個向量 `birthday`。 364 | - 將系統日期西元年份 `sys_date_year_num` 減去 `age` 得到各個船員的生日西元年份 `birth_year`。 365 | - 使用 `as.character()` 將 `birth_year` 轉成字元 `birth_year_char`。 366 | 367 | *** =hint 368 | - 輸入 `age <- straw_hat_df$age` 與 `birthday <- straw_hat_df$birthday` 將需要計算的欄位獨立出來。 369 | - 記得使用 `as.character()` 函數。 370 | 371 | *** =pre_exercise_code 372 | ```{r} 373 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 374 | sys_date <- Sys.Date() 375 | sys_date_year <- format(sys_date, '%Y') 376 | sys_date_year_num <- as.numeric(sys_date_year) 377 | rm(sys_date) 378 | rm(sys_date_year) 379 | ``` 380 | 381 | *** =sample_code 382 | ```{r} 383 | # straw_hat_df 與 sys_date_year_num 已預先載入 384 | 385 | # 宣告 age 向量 386 | age <- 387 | 388 | # 宣告 birthday 向量 389 | birthday <- 390 | 391 | # 用 sys_date_year_num 減去 age 並指派給 birth_year 392 | birth_year <- 393 | 394 | # 利用 as.character 將 birth_year 轉換成字元並指派給 birth_year_char 395 | birth_year_char <- 396 | 397 | # 將 birth_year 與 birth_year_char 輸出在 R Console 398 | 399 | ``` 400 | 401 | *** =solution 402 | ```{r} 403 | # straw_hat_df 與 sys_date_year_num 已預先載入 404 | 405 | # 宣告 age 向量 406 | age <- straw_hat_df$age 407 | 408 | # 宣告 birthday 向量 409 | birthday <- straw_hat_df$birthday 410 | 411 | # 用 sys_date_year_num 減去 age 並指派給 birth_year 412 | birth_year <- sys_date_year_num - age 413 | 414 | # 利用 as.character 將 birth_year 轉換成字元並指派給 birth_year_char 415 | birth_year_char <- as.character(birth_year) 416 | 417 | # 將 birth_year 與 birth_year_char 輸出在 R Console 418 | birth_year 419 | birth_year_char 420 | ``` 421 | 422 | *** =sct 423 | ```{r} 424 | msg = "確認是否有正確宣告 `age` 變數?" 425 | test_object("age", 426 | undefined_msg = msg, 427 | incorrect_msg = msg) 428 | 429 | msg = "確認是否有正確宣告 `birthday` 變數?" 430 | test_object("birthday", 431 | undefined_msg = msg, 432 | incorrect_msg = msg) 433 | 434 | msg = "確認是否有用 `sys_date_year_num` 減去 `age` 並指派給 `birth_year`?" 435 | test_object("birth_year", 436 | undefined_msg = msg, 437 | incorrect_msg = msg) 438 | 439 | msg = "確認是否有用 `as.character()` 將數值轉換為字元?" 440 | test_function("as.character", 441 | args = NULL, index = 1, 442 | eval = TRUE, 443 | eq_condition = "equivalent", 444 | not_called_msg = msg, 445 | args_not_specified_msg = NULL, 446 | incorrect_msg = msg) 447 | 448 | msg = "確認是否有正確宣告 `birth_year_char`?" 449 | test_object("birth_year_char", 450 | undefined_msg = msg, 451 | incorrect_msg = msg) 452 | 453 | msg = "確認是否有將 `birth_year` 與 `birth_year_char` 輸出在 R Console?" 454 | test_output_contains("birth_year", 455 | times = 1, 456 | incorrect_msg = msg) 457 | test_output_contains("birth_year_char", 458 | times = 1, 459 | incorrect_msg = msg) 460 | 461 | success_msg("太棒了,我們在下一個練習就可以大功告成,趕快來吧!") 462 | ``` 463 | 464 | --- type:NormalExercise lang:r xp:100 skills:4 key:a40e05d297 465 | ## 較難的衍生變數(3) 466 | 467 | 呼,終於要完成這個有點麻煩的衍生變數了!我們接下來要將剛剛生成的 `birth_year_char` 與 `birthday` 結合,字串的結合我們要使用 [`paste()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/paste) 函數: 468 | 469 | ```{r} 470 | char_pasted <- paste(char1, char2, sep = " ") 471 | ``` 472 | 473 | 注意預設的 `sep = ` 參數是空格,由於西元日期會以 `-` 連接,所以記得要使用 `sep = "-"`。結合好以後我們只需使用 [`as.Date()`](http://www.rdocumentation.org/packages/base/versions/3.3.1/topics/as.Date) 函數將字元轉換成**日期**格式,就可以將這個向量新增至資料框了! 474 | 475 | *** =instructions 476 | - 使用 `paste()` 函數將 `birth_year_char` 與 `birthday` 結合起來,成為 `birth_date_char`。 477 | - 使用 `as.Date()` 函數將 `birth_date_char` 轉成日期 `birth_date`。 478 | - 將 `birth_date` 新增至資料框。 479 | - 把 `straw_hat_df` 輸出在 R Console 看看。 480 | 481 | *** =hint 482 | - `paste()` 函數的參數記得要設為 `sep = "-"`。 483 | - 輸入 `straw_hat_df$birth_date <- birth_date` 就可以完成新增變數。 484 | - 在編輯區輸入 `straw_hat_df`。 485 | 486 | *** =pre_exercise_code 487 | ```{r} 488 | load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_1570/datasets/straw_hat_df.RData")) 489 | sys_date <- Sys.Date() 490 | sys_date_year <- format(sys_date, '%Y') 491 | sys_date_year_num <- as.numeric(sys_date_year) 492 | age <- straw_hat_df$age 493 | birthday <- straw_hat_df$birthday 494 | birth_year <- sys_date_year_num - age 495 | birth_year_char <- as.character(birth_year) 496 | rm(sys_date) 497 | rm(sys_date_year) 498 | rm(sys_date_year_num) 499 | rm(age) 500 | rm(birth_year) 501 | ``` 502 | 503 | *** =sample_code 504 | ```{r} 505 | # straw_hat_df 、 birthday 與 birth_year_char 已預先載入 506 | 507 | # 結合 birth_year_char 與 birthday 508 | birth_date_char <- paste(__, __, sep = "__") 509 | 510 | # 將 birth_date_char 轉成日期 birth_date 511 | birth_date <- 512 | 513 | # 將 birth_date 新增至資料框 514 | straw_hat_df$birth_date <- 515 | 516 | # 將資料框輸出在 R Console 517 | 518 | ``` 519 | 520 | *** =solution 521 | ```{r} 522 | # straw_hat_df 、 birthday 與 birth_year_char 已預先載入 523 | 524 | # 結合 birth_year_char 與 birthday 525 | birth_date_char <- paste(birth_year_char, birthday, sep = "-") 526 | 527 | # 將 birth_date_char 轉成日期 birth_date 528 | birth_date <- as.Date(birth_date_char) 529 | 530 | # 將 birth_date 新增至資料框 531 | straw_hat_df$birth_date <- birth_date 532 | 533 | # 將資料框輸出在 R Console 534 | straw_hat_df 535 | ``` 536 | 537 | *** =sct 538 | ```{r} 539 | msg = "確認是否有正確使用 `paste()` 函數?" 540 | test_function("paste", 541 | args = NULL, index = 1, 542 | eval = TRUE, 543 | eq_condition = "equivalent", 544 | not_called_msg = msg, 545 | args_not_specified_msg = NULL, 546 | incorrect_msg = msg) 547 | 548 | msg = "確認是否有使用 `paste()` 函數生成 `birth_date_char`?" 549 | test_object("birth_date_char", 550 | undefined_msg = msg, 551 | incorrect_msg = msg) 552 | 553 | msg = "確認是否有正確使用 `as.Date()` 函數?" 554 | test_function("as.Date", 555 | args = NULL, index = 1, 556 | eval = TRUE, 557 | eq_condition = "equivalent", 558 | not_called_msg = msg, 559 | args_not_specified_msg = NULL, 560 | incorrect_msg = msg) 561 | 562 | msg = "確認是否有使用 `as.Date()` 函數生成 `birth_date`?" 563 | test_object("birth_date", 564 | undefined_msg = msg, 565 | incorrect_msg = msg) 566 | 567 | msg = "確認是否有成功將 `birth_date` 新增至草帽海賊團資料框中?" 568 | 569 | test_data_frame("straw_hat_df", 570 | columns = "birth_date", 571 | undefined_msg = "確認你是否不小心將 `straw_hat_df` 移除了?", 572 | undefined_cols_msg = msg, 573 | incorrect_msg = msg) 574 | 575 | test_output_contains("straw_hat_df", 576 | incorrect_msg = "確認是否有將 `straw_hat_df` 輸出在 R Console?") 577 | 578 | success_msg("能夠完成這個系列的練習真是不簡單,看來你很有潛力成為草帽海賊團的第十個夥伴!") 579 | ``` --------------------------------------------------------------------------------