詳細功能介紹請參考這兩頁:Working with Data - Part 1 & Intro to R - Part 3
練習的部分可以參考 slides: Working with Data - Part 1 (pdf)
這幾個功能在 dplyr 這個 package 裡面,所以要先跑。同時要用內建檔案 mtcars 來練習,所以也要叫出來。下面還會用檔案資料 flights,因為它在 nycflights13 這個 packages 裡面,所以也需要安裝。
library(dplyr) library(nycflights13) mtcars flights |
下面先介紹一個觀看檔案的功能。
Glimpse function: columns run down the page, and data runs across, making it possible to see every column in a data frame
glimpse() 和平常看檔案的方式不一樣。我們平常看檔案的時候,variables 是在第一列(rows),每個欄位(column)是一個 variables。但用 glimpse() 的話,它會橫向顯示每個 variable 的數據值。
下面先用資料檔案 flights 練習。
dim(flights) |
dim: 顯示檔案資料的大小 dimension (row x column)
[1] 336776 19 |
上面顯示的結果告訴我們,共有 336776 個班機(observations),且用 19 個 variables 呈現各個班機的資訊。
glimpse(flights) |
Observations: 336,776 Variables: 19 $ year <int> 2013, 2013, 2013, 2013, 2013, 2013, ... $ month <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... $ day <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... $ dep_time <int> 517, 533, 542, 544, 554, 554, 555, ... |
上面用 glimpse() 功能可以看到每班飛機的資訊(variables)包括有 year, month, day, dep_time 等等。
5. Arrange function: order observations (rows)
沒特別指令的話會由小到大排列。
Default setting: order mpg values from small to large. (依 mpg 的大小排列)
arrange(mtcars, mpg) |
mpg cyl disp hp drat wt qsec vs am gear carb 1 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 2 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 3 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 4 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 5 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 |
如果要由大到小排列的話,則用:desc()
Use desc() to sort in descending order.
Order mpg from large to small.
arrange(mtcars, desc(mpg)) |
mpg cyl disp hp drat wt qsec vs am gear carb 1 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 2 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 3 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 4 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 5 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 |
如果有兩個 variables 的話,會先排第一個,然後再在第一個裡面排第二個的大小順序。
mtcars %>% arrange(cyl, gear) |
Arrange with cyl first; then within cyl, arrange gear.
上面的例子中,會先依照 cyl 的大小排列,再依 gear 的大小排列。
mpg cyl disp hp drat wt qsec vs am gear carb 1 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 2 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 3 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 4 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 5 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 |
如果想讓兩個 variables 都由大到小排列,可以分開寫,也可以合在一起。
Reorder the mtcars in descending order of mpg and displacement (disp)
mtcars %>% arrange(desc(carb), desc(mpg)) |
或寫成這樣:
mtcars %>% arrange(desc(carb, mpg)) |
mpg cyl disp hp drat wt qsec vs am gear carb 1 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 2 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 3 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 4 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 5 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 6 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 |
從上面可以看到是先依 carb 的大小排列,之後再依 mpg 的大小排列(最後四排當 carb 都是 4 的時候,mpg 是由大到小排列),但兩個都是由大到小。
Exercise
這邊我們用檔案資料 flights 來練習。
Q1. Which flights are the most delayed?
哪個班機起飛時間延遲最多,可以用 desc() 由大到小排列延遲的長度,第一個就是延遲最多的。下面先用 glimpse 呈現結果。
flights %>% arrange(desc(dep_delay)) %>% glimpse |
Observations: 336,776 Variables: 19 $ year <int> 2013, 2013, 2013, 2013, 2013, ... $ month <int> 1, 6, 1, 9, 7, 4, 3, 6, 7, 12, 5, 1, 2, ... $ day <int> 9, 15, 10, 20, 22, 10, 17, 27, 22, ... $ dep_time <int> 641, 1432, 1121, 1139, 845, 1100, 2321, ... $ sched_dep_time <int> 900, 1935, 1635, 1845, 1600, 1900, 810, ... $ dep_delay <dbl> 1301, 1137, 1126, 1014, 1005, 960, ... |
從上面顯示的最後一行 dep_delay 可以看到是由大到小排列。
如果不確定哪個 variable 是指延遲時間的話,可以用 ? 或 help() 的功能來查看:?flights 或是 help(flights)。
會在 R Studio 右下角的視窗中出現解釋框(如下圖,點圖可以放大),裡面寫:
dep_delay, arr_delay: Departure and arrival delays, in minutes. Negative times represent early departures/arrivals. |
下面是沒用 glimpse() 功能呈現,應該會比較清楚。
arrange(flights, desc(dep_delay)) |
# A tibble: 336,776 x 19 year month day dep_time sched_dep_time dep_delay arr_time <int> <int> <int> <int> <int> <dbl> <int> 1 2013 1 9 641 900 1301 1242 2 2013 6 15 1432 1935 1137 1607 3 2013 1 10 1121 1635 1126 1239 4 2013 9 20 1139 1845 1014 1457 5 2013 7 22 845 1600 1005 1044 6 2013 4 10 1100 1900 960 1342 7 2013 3 17 2321 810 911 135 8 2013 6 27 959 1900 899 1236 9 2013 7 22 2257 759 898 121 10 2013 12 5 756 1700 896 1058 # ... with 336,766 more rows, and 11 more variables: # carrier &arr_delay <dbl>,lt;chr>, flight <int>, tailnum <chr>, # origin <chr>, air_time <dbl>, distance <dbl>, hour <dbl>, # minute <dbl>, time_hour <dttm> |
Q2: Which flights caught up the most time during the flight?
哪班飛機趕上的時間最多,就是說即便是延遲起飛,但是仍然準時抵達的,也就是延遲時間最短的(比預計的飛行時間短),這邊用延遲起飛的時間減掉延遲抵達的時間,再由大到小排列。
flights %>% arrange(desc(dep_delay - arr_delay)) %>% glimpse |
Observations: 336,776 Variables: 19 $ year <int> 2013, 2013, 2013, 2013, 2013, 2013, ... $ month <int> 6, 2, 2, 5, 2, 7, 7, 12, 5, 11, 5, 5, ... $ day <int> 13, 26, 23, 13, 27, 14, 17, 27, 2, 13, ... $ dep_time <int> 1907, 1000, 1226, 1917, 924, 1917, ... $ sched_dep_time <int> 1512, 900, 900, 1900, 900, 1829, 1930, ... |
不用 glimpse 顯示:
arrange(flights, desc(dep_delay - arr_delay)) |
# A tibble: 336,776 x 19 year month day dep_time sched_dep_time dep_delay arr_time <int> <int> <int> <int> <int> <dbl> <int> 1 2013 6 13 1907 1512 235 2134 2 2013 2 26 1000 900 60 1513 3 2013 2 23 1226 900 206 1746 4 2013 5 13 1917 1900 17 2149 5 2013 2 27 924 900 24 1448 6 2013 7 14 1917 1829 48 2109 7 2013 7 17 2004 1930 34 2224 8 2013 12 27 1719 1648 31 1956 9 2013 5 2 1947 1949 -2 2209 10 2013 11 13 2024 2015 9 2251 # ... with 336,766 more rows, and 11 more variables: # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>, # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, # hour <dbl>, minute <dbl>, time_hour <dttm> |
可以指定 catchup 為 flights,再帶入 arrange,或是用 head 只顯示前十個 carrier。
flights %>% arrange(desc(dep_delay - arr_delay)) head(catchup$carrier, 10) |
[1] "EV" "HA" "HA" "DL" "HA" "UA" "UA" "UA" "UA" "DL" |
如果只看資料的前十個的話,則是下面這樣。
head(flights$carrier, 10) |
[1] "UA" "UA" "AA" "B6" "DL" "UA" "B6" "EV" "B6" "AA" |
6. Mutate function: 設定新的 variable,新設定的 variable 會顯示在最後一欄。
Make new variables: disp_l and wt_kg
1L = 61.0237 cu.in. (cubic inch)
1kg = 2.2 lbs
檔案資料裡面的 disp 單位是 cu.in.,我們把它轉換成 L,設定其為 disp_l。同時也把裡面原本單位為磅(lbs)的 wt 換算成 kg,指定其為 wt_kg。新訂的 disp_l 和 wt_kg 會顯示在最後兩的 column。
mtcars %>% mutate(disp_l = disp/61.0237, wt_kg = wt/2.2) |
mpg cyl disp hp drat wt qsec vs am gear carb disp_l wt_kg 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 2.621932 1.1909091 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 2.621932 1.3068182 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 1.769804 1.0545455 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 4.227866 1.4613636 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 5.899347 1.5636364 |
把重量換算成噸,指定其為:wt_tonnes
Include a variable for weight in tonnes (1t = 2,204.6 lbs)
mtcars %>% mutate(wt_tones = wt / 2.2046) |
mpg cyl disp hp drat wt qsec vs am gear carb wt_tones 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 1.1884242 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 1.3040914 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 1.0523451 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 1.4583144 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 1.5603738 |
transmute: leave only the new variables
如果用 transmute() 的話,就只會顯示新訂的 disp_1 和 wt_kg。
mtcars %>% transmute(disp_l = disp/61.0237, wt_kg = wt/2.2) |
disp_l wt_kg 1 2.621932 1.1909091 2 2.621932 1.3068182 3 1.769804 1.0545455 4 4.227866 1.4613636 5 5.899347 1.5636364 6 3.687092 1.5727273 |
Exercise
Q1. Compute speed in mph from time (in minutes) and distance (in miles)
同樣可以用 ?flights 查詢:
distance: Distance between airports, in miles air_time: Amount of time spent in the air, in minutes |
計算飛機的速度:mph = miles per hour
也就是飛行的距離 distance (in miles) 除以飛行的時間 air_time (in minutes)。
因為 air_time 是以分鐘為單位,所以我們必須先把它轉換成小時,也就是:air_time / 60
下面把速度指定為 speed。
mutate(flights, speed = distance / (air_time / 60)) |
# A tibble: 336,776 x 20 year month day dep_time sched_dep_time dep_delay arr_time <int> <int> <int> <int> <int> <dbl> <int> 1 2013 1 1 517 515 2 830 2 2013 1 1 533 529 4 850 3 2013 1 1 542 540 2 923 4 2013 1 1 544 545 -1 1004 5 2013 1 1 554 600 -6 812 6 2013 1 1 554 558 -4 740 7 2013 1 1 555 600 -5 913 8 2013 1 1 557 600 -3 709 9 2013 1 1 557 600 -3 838 10 2013 1 1 558 600 -2 753 # ... with 336,766 more rows, and 12 more variables: # arr_delay <dbl>, carrier <chr> flight <int>, tailnum <chr>, # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, # hour <dbl>, minute <dbl>, time_hour <dttm>, speed <dbl> |
顯示整個檔案太長,看不到後面計算出來的 speed,所以用 select() 的功能挑出我們想看的幾個 variables。如果忘記 select() 是什麼、怎麼用的話,可以看前一篇。
mutate(flights, speed = distance / (air_time / 60)) %>% select(carrier, distance, air_time, speed) |
# A tibble: 336,776 x 4 carrier distance air_time speed <chr> <dbl> <dbl> <dbl> 1 UA 1400 227 370.0441 2 UA 1416 227 374.2731 3 AA 1089 160 408.3750 4 B6 1576 183 516.7213 5 DL 762 116 394.1379 6 UA 719 150 287.6000 7 B6 1065 158 404.4304 8 EV 229 53 259.2453 9 B6 944 140 404.5714 10 AA 733 138 318.6957 # ... with 336,766 more rows |
Q2. Which flight flew the fastest?
哪個班機的速度最快?可以用 arrange() 功能由大到小排列出來,跟上面一樣只挑出我們想看的幾個 variables 來看。
flights %>% mutate(speed = distance / (air_time / 60)) %>% arrange(desc(speed)) %>% select(carrier, distance, air_time, speed) |
# A tibble: 336,776 x 4 carrier distance air_time speed <chr> <dbl> <dbl> <dbl> 1 DL 762 65 703.3846 2 EV 1008 93 650.3226 3 EV 594 55 648.0000 4 EV 748 70 641.1429 5 DL 1035 105 591.4286 6 DL 1598 170 564.0000 7 B6 1598 172 557.4419 8 AA 1623 175 556.4571 9 DL 1598 173 554.2197 10 B6 1598 173 554.2197 # ... with 336,766 more rows |
Q3. 把上面班機延遲練習的 Q2,用 select() 的功能挑出我們想看的幾項出來。
flights %>% mutate(delay_time = dep_delay - arr_delay) %>% arrange(desc(delay_time)) %>% select(carrier, dep_time, arr_time, air_time, dep_delay, arr_delay, delay_time) |
# A tibble: 336,776 x 7 carrier dep_time arr_time air_time dep_delay arr_delay delay_time <chr> <int> <int> <dbl> <dbl> <dbl> <dbl> 1 EV 1907 2134 126 235 126 109 2 HA 1000 1513 584 60 -27 87 3 HA 1226 1746 599 206 126 80 4 DL 1917 2149 313 17 -62 79 5 HA 924 1448 589 24 -52 76 6 UA 1917 2109 274 48 -26 74 7 UA 2004 2224 295 34 -40 74 8 UA 1719 1956 324 31 -42 73 9 UA 1947 2209 300 -2 -75 73 10 DL 2024 2251 311 9 -63 72 # ... with 336,766 more rows |
可以和上面排列前十的 carrier 的結果比對,看排列是不是一樣的。
7. Summarise / Summarize
功能和 mutate() 有點像,不一樣的是它會產生一個新的 data frame,並且是那欄(也就是那個 variable)所有觀察資料的總結。
Summarise works in an analogous way to mutate, except instead of adding columns to an existing data frame, it creates a new data frame. This is particularly useful in conjunction with ddply as it makes it easy to perform group-wise summaries. |
例如算出 mpg 的平均值,可以用 mean() 的功能這樣算:
mean(mtcars$mpg) |
[1] 20.09062 |
如果用 mutate() 的話會是這樣:
mutate(mtcars, mean(mpg)) |
mpg cyl disp hp drat wt qsec vs am gear carb mean(mpg) 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 20.09062 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 20.09062 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 20.09062 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 20.09062 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 20.09062 |
同樣是算出 mean,但它會放在最後一欄,所以所有數值都一樣,因為它是全部觀察算出來的平均值。
如果用 summarise() 的話則是這樣,以一個 data frame 的樣式呈現出來:
summarise(mtcars, mean(mpg)) |
mean(mpg) 1 20.09062 |
也可以幫平均值指定一個名稱 mpg_mean,直接寫在裡面即可。
summarise(mtcars, mpg_mean = mean(mpg) |
mpg_mean 1 20.09062 |
也可以設定三個,例如把 mpg 的平均值設為 mean_mpg,把重量的中間值設為 median_wt,然後把這兩者的比例設為 ratio。
找出中間值用的功能是:median()
mtcars %>% summarise(mean_mpg = mean(mpg), median_wt = median(wt), ratio = mean_mpg/median_wt) |
mean_mpg median_wt ratio 1 20.09062 3.325 6.042293 |
也可以全部寫在一行,下面同時把 mpg 的平均值直接設為 mpg,wt 的中間值設為 wt,把兩者的比例設為 ratio。
summarise(mtcars, mpg = mean(mpg), wt = median(wt), ratio = mpg/wt) |
mpg wt ratio 1 20.09062 3.325 6.042293 |
除了算全部的平均值外,也可以分組算,例如算出 cyl 裡各種觀察值的平均值。下面先用 levels() 看 cyl 裡面有哪幾種,因為 cyl 的觀察值是數字,需要先把它換成 factor。
levels(factor(mtcars$cyl)) |
[1] "4" "6" "8" |
由上面結果可以看出 cyl 的觀察值有三種:4, 6, 8。如果要看各個的 mpg 和重量平均值,可以用 group_by() 的功能。
mtcars %>% group_by(cyl) %>% summarise(mean_mpg = mean(mpg), median_wt = median(wt)) |
# A tibble: 3 x 3 cyl mean_mpg median_wt <dbl> <dbl> <dbl> 1 4 26.66364 2.200 2 6 19.74286 3.215 3 8 15.10000 3.755 |
也可以在一組裡面再分組算平均值,例如先用 am 分組後,在再裡面用 cyl 分組,先分的那個放前面,所以語法會是:group_by(am, cyl)
mtcars %>% group_by(am, cyl) %>% summarise(mpg = mean(mpg), wt = median(wt)) |
# A tibble: 6 x 4 # Groups: am [?] am cyl mpg wt <dbl> <dbl> <dbl> <dbl> 1 0 4 22.90000 3.1500 2 0 6 19.12500 3.4400 3 0 8 15.05000 3.8100 4 1 4 28.07500 2.0375 5 1 6 20.56667 2.7700 6 1 8 15.40000 3.3700 |
因為用 summarise() 算出來的結果本身就會轉換成一個 data frame,所以可以把這個 data frame 指定一個名稱,例如為 cars_am_cyl,這樣之後想要看的時候便不需要打全部的語法,只要叫出 cars_am_cyl 即可看。
cars_am_cyl <- mtcars %>% group_by(am, cyl) %>% summarise(mpg = mean(mpg), wt = median(wt)) cars_am_cyl |
因為 cars_am_cyl 已經是一個 data frame,也可以直接用它來做運算,因為上面設定時已經先用 am 分好組了,所以算平均值的時候會依這個分。
cars_am_cyl %>% summarise(mpg = mean(mpg), wt = median(wt)) |
# A tibble: 2 x
am mpg wt <dbl> <dbl> <dbl> 1 0 19.02500 3.44 2 1 21.34722 2.77 |
也可以相反設試試看,先用 cyl 分組後再依 am 分組運算,也就是 group_by(cyl, am),然後和上面比較有何不同。
cars_cyl_am <- mtcars %>% group_by(cyl, am) %>% summarise(mpg = mean(mpg), wt = median(wt)) cars_cyl_am |
# A tibble: 6 x 4 # Groups: cyl [?] cyl am mpg wt <dbl> <dbl> <dbl> <dbl> 1 4 0 22.90000 3.1500 2 4 1 28.07500 2.0375 3 6 0 19.12500 3.4400 4 6 1 20.56667 2.7700 5 8 0 15.05000 3.8100 6 8 1 15.40000 3.3700 |
因為上面是先用 cyl 分組,所以接下來用 cars_cyl_am 來做運算的話,會算出 cyl 裡各組的平均值。
cars_cyl_am %>% summarise(mpg = mean(mpg), wt = median(wt)) |
# A tibble: 3 x 3 cyl mpg wt <dbl> <dbl> <dbl> 1 4 25.48750 2.59375 2 6 19.84583 3.10500 3 8 15.22500 3.59000 |
Exercise
Q1. Compute the minimum and maximum displacement for each engine type (vs) by transmission type (am)
在各個引擎的種類中依 am 分組後,找出其中的最大值和最小值,因此要先依引擎分類,再在其中依 am 分組,也就是:group_by(vs, am)
最大值和最小值的功能為:max() 和 min()
mtcars %>% group_by(vs, am) %>% summarise(min = min(disp), max = max(disp)) |
# A tibble: 4 x 4 # Groups: vs [?] vs am min max <dbl> <dbl> <dbl> <dbl> 1 0 0 275.8 472 2 0 1 120.3 351 3 1 0 120.1 258 4 1 1 71.1 121 |
Q2. Which destinations have the highest average delays?
flights %>% group_by(dest) %>% summarise(avg_delay = mean(arr_delay, na.rm = TRUE)) %>% arrange(desc(avg_delay)) |
# A tibble: 105 x 2 dest avg_delay <chr> <dbl> 1 CAE 41.76415 2 TUL 33.65986 3 OKC 30.61905 4 JAC 28.09524 5 TYS 24.06920 6 MSN 20.19604 7 RIC 20.11125 8 CAK 19.69834 9 DSM 19.00574 10 GRR 18.18956 # ... with 95 more rows |
8. Boxplot
接下來試著畫箱圖,如果想畫出在 cyl < 8 的資料中,mpg 對 cyl 的反應,也就是:
x-axis: cyl < 8 y-axis: mpg, response to cyl |
boxplot 的語法是:boxplot(formula, data = )
formula 是指兩軸(也就是兩個 variables)的關係,在這裡是: y ~ x
表示 Y-axis 對 X-axis 的反應,所以也就是:boxplot(y ~ x, data = )
最後用 subset = 的功能挑出你要的,在這個例子裡就是 cyl < 8。
boxplot(mpg ~ cyl, data = mtcars, subset= cyl < 8) |
也可以用 %>% 分開寫。
You can use . as a placeholder when the “data” argument is in the second position.
mtcars %>% filter(cyl < 8) %>% boxplot(mpg ~ cyl, data = . ) |
在上面的語法裡,當前面已經表示過用的資料是 mtcars 的時候,後面在 boxplot() 裡面 data 的部分就可以用 "." 替代,也就是:data = .
也可以用 ggplot2 來畫圖,用 ggplot 裡的 geom_boxplot() 畫的話,語法就是這樣:
ggplot(mtcars %>% filter(cyl < 8), aes(factor(cyl), mpg)) + geom_boxplot() |
因為 cyl 是數字,所以要需要先把它變成 factor,想更了解的話可以參考這篇:R | ggplot: Point plot & Box plot
也可以先把畫圖要用的資料用 subset() 的功能挑出來,也就是 cyl < 8 的部分。我們可以把挑出來的部分指定成一個新的 data frame,下面我們把指定其為 cyl_sub,然後再用它來畫圖。
cyl_sub <- subset(mtcars, cyl < 8) ggplot(cyl_sub, aes(factor(cyl), mpg)) + geom_boxplot() |
好了,這篇就先到這吧。