library(nycflights13)
library(tidyverse)
#使用dplyr進行數(shù)據(jù)轉(zhuǎn)換
#加載 tidyverse 時辰企,仔細查看輸出的沖突信息,
#它會告訴你 dplyr 覆蓋了基礎(chǔ) R 包中的哪些 函數(shù)。
#如果想要在加載 dplyr 后使用這些函數(shù)的基礎(chǔ)版本退个,
#那么你應(yīng)該使用它們的完整名 稱:stats::filter() 和 stats::lag()执赡。
#nycflights13這個數(shù)據(jù)框包含了2013年從紐約市出發(fā)的所有336776次航班的信息姚垃。
flights
#只顯示了前幾行和適合屏幕寬度的幾列。
#(要想看到整個數(shù)據(jù)集坏怪,可以使用 View(flights) 在 RStudio 查看器中打開數(shù)據(jù)集贝润。)
View(flights)
#輸出有差別是因為 flights 是一個 tibble。
#列名下面有一行 3 個或 4 個字母的縮寫陕悬。它們描述了每個變量的類型。
#? int 表示整數(shù)型變量按傅。
#? dbl 表示雙精度浮點數(shù)型變量捉超,或稱實數(shù)。
#? chr 表示字符向量唯绍,或稱字符串拼岳。
#? dttm 表示日期時間(日期 + 時間)型變量。
#? lgl 表示邏輯型變量况芒,是一個僅包括 TRUE 和 FALSE 的向量惜纸。
#? fctr 表示因子,R 用其來表示具有固定數(shù)目的值的分類變量绝骚。
#? date 表示日期型變量耐版。
#學(xué)習(xí) 5 個 dplyr 核心函數(shù)
#? 按值篩選觀測(filter())。
#? 對行進行重新排序(arrange())压汪。
#? 按名稱選取變量(select())粪牲。
#? 使用現(xiàn)有變量的函數(shù)創(chuàng)建新變量(mutate())。
#? 將多個值總結(jié)為一個摘要統(tǒng)計量(summarize())止剖。
#5 個函數(shù)的工作方式都是相同的腺阳。
#(1) 第一個參數(shù)是一個數(shù)據(jù)框。
#(2) 隨后的參數(shù)使用變量名稱(不帶引號)描述了在數(shù)據(jù)框上進行的操作穿香。
#(3) 輸出結(jié)果是一個新數(shù)據(jù)框亭引。
#filter() 函數(shù)可以基于觀測的值篩選出一個觀測子集。
#第一個參數(shù)是數(shù)據(jù)框名稱皮获,
#第二個參數(shù)以及隨后的參數(shù)是用來篩選數(shù)據(jù)框的表達式焙蚓。
#篩選出 1 月 1 日的所有航班
filter(flights, month == 1, day == 1)
#dplyr 函數(shù)從來不修改輸入,
#因此洒宝,如果想要保存函數(shù)結(jié)果主届,那么你就需要使用賦值操作符 <-
jan1 <- filter(flights, month == 1, day == 1)
#R 要么輸出結(jié)果,要么將結(jié)果保存在一個變量中待德。
#如果想同時完成這兩種操作君丁,那么你可以用括號將賦值語句括起來
(jan1 <- filter(flights,month==1,day==1))
#R 提供了一套標準的比較運算符:>、>=将宪、<绘闷、<=橡庞、!=(不等于)和 ==(等于)。
#易犯錯誤使用 = 而不是 == 來測試是否相等
filter(flights, month = 1)
#> Error: filter() takes unnamed arguments. Do you need `==`?
#使用 == 進行比較浮點數(shù)
sqrt(2) ^ 2 == 2
1/49 * 49 == 1
#計算機使用的是有限精度運算(顯然無法存儲無限位的數(shù))印蔗,
#因此請記住扒最,你看到的每個 數(shù)都是一個近似值。
#比較浮點數(shù)是否相等時华嘹,不能使用 ==吧趣,而應(yīng)該使用 near()
near(sqrt(2) ^ 2, 2)
near(1 / 49 * 49, 1)
#filter() 中的多個參數(shù)是由“與”組合起來的
#每個表達式都必須為真才能讓一行觀測包含在輸出中。
#使用布爾運算符:& 表示“與”耙厚、| 表示 “或”强挫、! 表示“非”
#找出 11 月或 12 月出發(fā)的所有航班
filter(flights, month == 11 | month == 12)
#不能寫成filter(flights, month == 11 | 12) 這種形式
#代碼中的含義是找出所有出發(fā)月份為 11 | 12 的航班。
#11 | 12 這個 邏輯表達式的值為 TRUE
#TRUE 就是 1薛躬,所以這段代碼找出的不是11月或12月出發(fā)的航班俯渤,
#而是 1 月出發(fā)的所有航班。
#這種問題有一個有用的簡寫形式:x %in% y型宝。
#這會選取出x是y中的一個值時的所有行八匠。
nov_dec <- filter(flights, month %in% c(11, 12))
#德摩根定律將復(fù)雜的篩選條件進行簡化
# !(x & y)等價于!x | !y
# !(x | y)等價于!x & !y
#延誤時間(到達或出發(fā))不多于2小時的航班
filter(flights, !(arr_delay > 120 | dep_delay > 120))
filter(flights, arr_delay <= 120, dep_delay <= 120)
#除 & 和 | 之外,R 中還有 && 和 || 運算符趴酣。
#先不要使用這兩個運算符!
#只要 filter() 函數(shù)中使用的是復(fù)雜的梨树、包含多個部分的表達式,
#就需要考慮用一個明確的 變量來代替它岖寞。
#這樣檢查代碼會容易很多劝萤。
#缺失值,或稱 NA(not available慎璧, 不可用)床嫌。
#NA 表示未知的值,因此缺失值是“可傳染的”胸私。
NA > 5
#> [1] NA
10 == NA
#> [1] NA
NA + 10
#> [1] NA
NA / 2
#> [1] NA
NA == NA
#> [1] NA
# 令x為Mary的年齡厌处。我們不知道她有多大。
x <- NA
# 令y為John的年齡岁疼。我們不知道他有多大阔涉。
y <- NA
# John和Mary的年齡是相同的嗎?
x == y
#> [1] NA
# 我們不知道!
#如果想要確定一個值是否為缺失值,可以使用 is.na() 函數(shù):
is.na(x)
#> [1] TRUE
#filter() 只能篩選出條件為 TRUE 的行;
#它會排除那些條件為 FALSE 和 NA 的行捷绒。
#如果想保留缺失值瑰排,可以明確指出:
? df <- tibble(x = c(1, NA, 3))
? filter(df, x > 1)
? filter(df, is.na(x) | x > 1)
#到達時間延誤 2 小時或更多的航班。
? filter(flights,arr_delay>=120)
#飛往休斯頓(IAH機場或HOU機場)的航班暖侨。
? filter(flights,dest=='IAH'|dest=='HOU')
? filter(flights,dest %in% c('IAH','HOU'))
#由聯(lián)合航空(United)椭住、美利堅航空(American)或三角洲航空(Delta)運營的航班。
? filter(flights,carrier %in% c('UA','AA','DL'))
#夏季(7月字逗、8月和9月)出發(fā)的航班京郑。
? filter(flights,month %in% c(7,8,9))
? filter(flights, month >= 7, month <= 9)
? filter(flights, between(month,7,9))
#到達時間延誤超過 2 小時宅广,但出發(fā)時間沒有延誤的航班。
? filter(flights,dep_delay<=0,arr_delay>120)
? filter(flights,!(dep_delay>0|arr_delay<=120))
#延誤至少 1 小時些举,但飛行過程彌補回 30 分鐘的航班跟狱。
? filter(flights, dep_delay >= 60, dep_delay - arr_delay > 30)
#出發(fā)時間在午夜和早上6點之間(包括0點和6點)的航班。
? filter(flights, dep_time<=600)
#dep_time 有缺失值的航班有多少??
? filter(flights, is.na(dep_time))
? NA ^ 0
#[1] 1
? NA | TRUE
#[1] TRUE
? FALSE & NA
#[1] FALSE
? NA * 0
#[1] NA
#使用arrange()排列行
#arrange() 函數(shù)的工作方式與 filter() 函數(shù)非常相似户魏,
#但前者不是選擇行驶臊,而是改變行的順序。
#它接受一個數(shù)據(jù)框和一組作為排序依據(jù)的列名(或者更復(fù)雜的表達式)作為參數(shù)叼丑。
#如果列名不只一個关翎,那么就使用后面的列在前面排序的基礎(chǔ)上繼續(xù)排序:
? arrange(flights, year, month, day)
#使用 desc() 可以按列進行降序排序
? arrange(flights, desc(arr_delay))
#缺失值總是排在最后:
? df <- tibble(x = c(5, 2, NA))
? arrange(df, x)
? arrange(df, desc(x))
#如何使用 arrange() 將缺失值排在最前面?(提示:使用 is.na()。)
? arrange(df, desc(is.na(x)))
#對 flights 排序以找出延誤時間最長的航班幢码。找出出發(fā)時間最早的航班笤休。
? arrange(flights,desc(arr_delay))
? arrange(flights,dep_time)
#對 flights 排序以找出速度最快的航班尖飞。
#哪個航班的飛行時間最長?哪個最短?
#使用select()選擇列
#select() 函數(shù)可以讓你快速生成一個有用的變量子集症副。
# 按名稱選擇列
? select(flights, year, month, day)
# 選擇“year”和“day”之間的所有列(包括“year”和“day”)
? select(flights, year:day)
# 選擇不在“year”和“day”之間的所有列(不包括“year”和“day”)
? select(flights, -(year:day))
#還可以在 select () 函數(shù)中使用一些輔助函數(shù)。
#? ? starts_with("abc"):匹配以“abc”開頭的名稱政基。
#? ? ends_with("xyz"):匹配以“xyz”結(jié)尾的名稱贞铣。
#? ? contains("ijk"):匹配包含“ijk”的名稱。
#? ? matches("(.)\\1"):選擇匹配正則表達式的那些變量沮明。
#? 這個正則表達式會匹配名稱中有重復(fù)字符的變量辕坝。
#? ? num_range("x", 1:3):匹配 x1、x2 和 x3荐健。
#select() 可以重命名變量酱畅,但我們很少這樣使用它,
#因為這樣會丟掉所有未明確提及的變 量江场。
#我們應(yīng)該使用 select() 函數(shù)的變體 rename() 函數(shù)來重命名變量纺酸,以保留所有未明確 提及的變量:
? rename(flights, tail_num = tailnum)
#將 select() 函數(shù)和 everything() 輔助函數(shù)結(jié)合起來使用。
#當(dāng)想要將幾個變量移到數(shù)據(jù)框開頭時址否,這種用法非常奏效:
? select(flights, time_hour, air_time, everything())
#從 flights 數(shù)據(jù)集中選擇 dep_time餐蔬、dep_delay、arr_time 和 arr_delay佑附,通過頭腦風(fēng)暴找出盡可能多的方法樊诺。
? select(flights, starts_with("dep_"), starts_with("arr_"))
? select(flights,dep_time,dep_delay,arr_time,arr_delay)
#select忽略重復(fù)項,只選第一個。
? ? select(flights, year, month, day, year, year)
# one_of() 函數(shù)
? ? vars <- c(
? ? ? "year", "month", "day", "dep_delay", "arr_delay"
? ? )
? ? select(flights,one_of(vars))
#選擇輔助函數(shù)處理大小寫的默認方式忽略大小寫
? ? select(flights, contains("TIME"))
# contains忽略了大小寫音同,有個參數(shù)可以改變
? ? select(flights, contains("TIME", ignore.case = FALSE))
#使用mutate()添加新變量
#除了選擇現(xiàn)有的列词爬,我們還經(jīng)常需要添加新列,新列是現(xiàn)有列的函數(shù)权均。
#這就是 mutate() 函數(shù)的作用缸夹。
#mutate() 總是將新列添加在數(shù)據(jù)集的最后痪寻,
#因此我們需要先創(chuàng)建一個更狹窄的數(shù)據(jù)集,以便能夠看到新變量虽惭。
#當(dāng)使用 RStudio 時橡类,查看所有列的最簡單的方法就是使用 View() 函數(shù)
? ? flights_sml <- select(flights,
? ? ? ? ? ? ? ? ? ? ? ? ? year:day,
? ? ? ? ? ? ? ? ? ? ? ? ? ends_with("delay"),
? ? ? ? ? ? ? ? ? ? ? ? ? distance,
? ? ? ? ? ? ? ? ? ? ? ? ? air_time
? ? )
? ? mutate(flights_sml,
? ? ? ? ? gain = arr_delay - dep_delay,
? ? ? ? ? speed = distance / air_time * 60
? ? )
#一旦創(chuàng)建,新列就可以立即使用
? ? mutate(flights_sml,
? ? ? ? ? gain = arr_delay - dep_delay,
? ? ? ? ? hours = air_time / 60,
? ? ? ? ? gain_per_hour = gain / hours
? ? )
#如果只想保留新變量芽唇,可以使用 transmute() 函數(shù):
? ? transmute(flights,
? ? ? ? ? ? ? gain = arr_delay - dep_delay,
? ? ? ? ? ? ? hours = air_time / 60,
? ? ? ? ? ? ? gain_per_hour = gain / hours
? ? )? ?
#創(chuàng)建新變量的多種函數(shù)可供你同 mutate() 一同使用顾画。
#最重要的一點是,這種函數(shù)必須是向量化的:
#它必須接受一個向量作為輸入匆笤,并返回一個向量作為輸出研侣,
#而且輸入向量與輸出向量具有同樣數(shù)目的分量。
#算術(shù)運算符:+炮捧、-庶诡、*、/咆课、^
#當(dāng)某個參數(shù)是單個數(shù)值時末誓,這種方式是最有效的:
#? ? air_ time / 60、hours * 60 + minute 等书蚪。
#聚集函數(shù)
#x / sum(x)可以計算出各個分量在總數(shù)中的比例喇澡,
#y – mean(y)可以計算出分量與均值之間的差值
#模運算符:%/% 和 %%
#%/%(整數(shù)除法)和%%(求余)滿足x == y * (x %/% y) + (x %% y)。
#模運算非常好用殊校,因為它可以拆分整數(shù)晴玖。
#在航班數(shù)據(jù)集中,你可以根據(jù) dep_time 計算出 hour 和 minute:
? ? transmute(flights,
? ? ? ? ? ? ? dep_time,
? ? ? ? ? ? ? hour = dep_time %/% 100,
? ? ? ? ? ? ? minute = dep_time %% 100
? ? )
#對數(shù)函數(shù):log()为流、log2() 和 log10()
#在處理取值范圍橫跨多個數(shù)量級的數(shù)據(jù)時呕屎,對數(shù)是特別有用的一種轉(zhuǎn)換方式。
#它還可以將乘法轉(zhuǎn)換成加法敬察。
#其他條件相同的情況下秀睛,推薦使用 log2() 函數(shù),
#因為很容易對其進行解釋:對數(shù)標度的數(shù)值增加 1 個單位静汤,意味著初始數(shù)值加倍;
#減少1個單位琅催,則意味著初始數(shù)值減半。? ?
#偏移函數(shù)
#lead() 和 lag() 函數(shù)可以返回一個序列的領(lǐng)先值和滯后值虫给。
#它們可以計算出序列的移動差值(如x – lag(x))或發(fā)現(xiàn)序列何時發(fā)生了變化(x != lag(x))藤抡。
#它們與group_by() 組合使用時特別有用,你很快就會學(xué)到 group_by() 這個函數(shù)
? ? (x <- 1:10)
? ? #> [1] 1 2 3 4 5 6 7 8 9 10
? ? lag(x)
? ? #> [1] NA 1 2 3 4 5 6 7 8 9
? ? lead(x)
? ? #> [1] 2 3 4 5 6 7 8 9 10 NA
#累加和滾動聚合
#R 提供了計算累加和抹估、累加積缠黍、累加最小值和累加最大值的函數(shù):
#cumsum()、cumprod()药蜻、 commin() 和 cummax();
#dplyr 還提供了 cummean() 函數(shù)以計算累加均值瓷式。
#如果想要計算滾動聚合(即滾動窗口求和)替饿,那么可以嘗試使用 RcppRoll 包:
? ? cumsum(x)
? ? #> [1] 1 3 6 10 15 21 28 36 45 55
? ? cummean(x)
? ? #> [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
#邏輯比較:<、<=贸典、>视卢、>= 和 !=
#? ? 如果需要進行一系列復(fù)雜的邏輯運算,
#? ? 那么最好將中間結(jié)果保存在新變量中廊驼,
#? ? 這樣就可以檢查是否每一步都符合預(yù)期据过。
#排秩
#min_rank() 函數(shù)可以完成最常用的排秩任務(wù) (如第一、第二妒挎、第三绳锅、第四)。
#默認的排秩方式是酝掩,最小的值獲得最前面的名次鳞芙,
#使用desc(x) 可以讓最大的值獲得最前面的名次
? ? y <- c(1, 2, 2, NA, 3, 4)
? ? min_rank(y)
? ? #> [1] 1 2 2 NA 4 5
? ? min_rank(desc(y))
? ? #> [1]? 5? 3? 3 NA? 2? 1
#? ? min_rank() 無法滿足需要,
#? ? 那么可以看一下其變體 row_number()期虾、dense_rank()原朝、 percent_rank()、cume_dist() 和 ntile()
? ? row_number(y)
? ? #> [1] 1 2 3 NA 4 5
? ? dense_rank(y)
? ? #> [1] 1 2 2 NA 3 4
? ? percent_rank(y)
? ? #> [1] 0.00 0.25 0.25 NA 0.75 1.00
? ? cume_dist(y)
? ? #> [1] 0.2 0.6 0.6 NA 0.8 1.0
#使用summarize()進行分組摘要? ?
#它可以將數(shù)據(jù)框折疊成一行
summarize(flights, delay = mean(dep_delay, na.rm = TRUE))
? ? # A tibble: 1 × 1
? ? #> delay
? ? #> <dbl>
? ? #> 1 12.6
#group_by() 可以將分析單位從整個數(shù)據(jù)集更改為單個分組彻消。
#在分組后的數(shù)據(jù)框上使用 dplyr 函數(shù)時竿拆,它們會自動地應(yīng)用到每個分組宙拉。
#group_by() 和 summarize() 的組合構(gòu)成了使用 dplyr 包時最常用的操作之一
#分組摘要
#對按日期分組的一個數(shù)據(jù)框應(yīng)用與上面完全相同的代碼宾尚,
#那么我們就可以得到每日平均延誤時間
by_day <- group_by(flights, year, month, day)
summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))
#介紹一個功能強大的新概念:管道
#研究每個目的地的距離和平均延誤時間之間的關(guān)系
#完成數(shù)據(jù)準備需要 3 步。
#(1) 按照目的地對航班進行分組谢澈。
by_dest <- group_by(flights, dest)
#(2) 進行摘要統(tǒng)計煌贴,計算距離、平均延誤時間和航班數(shù)量锥忿。
delay <- summarize(by_dest,
? ? ? ? ? ? ? ? ? count = n(),
? ? ? ? ? ? ? ? ? dist = mean(distance, na.rm = TRUE),
? ? ? ? ? ? ? ? ? delay = mean(arr_delay, na.rm = TRUE)
)
#(3) 通過篩選除去噪聲點和火奴魯魯機場牛郑,因為到達該機場的距離幾乎是到離它最近機場的距離的 2 倍。
delay <- filter(delay, count > 20, dest != "HNL")
#這段代碼寫起來有點令人泄氣敬鬓,因為不得不對每個中間數(shù)據(jù)框命名淹朋,盡管我們根本不關(guān)心這一點。
#命名是很難的钉答,這樣做會影響我們的分析速度础芍。
#解決這個問題的另一種方法是使用管道,%>%
delays <- flights %>%
? group_by(dest) %>%
? summarize(
? ? count = n(),
? ? dist = mean(distance, na.rm = TRUE),
? ? delay = mean(arr_delay, na.rm = TRUE)
? ) %>%
? filter(count > 20, dest != "HNL")
#這種方法的重點在于轉(zhuǎn)換的過程数尿,而不是轉(zhuǎn)換的對象仑性,
#這使得代碼具有更好的可讀性。
#你可以將其讀作一串命令式語句:分組右蹦,然后摘要統(tǒng)計诊杆,然后進行篩選歼捐。
#在閱讀代碼時,%>% 最好讀作“然后”晨汹。
#使用這種方法時豹储,x %>% f(y)會轉(zhuǎn)換為f(x, y),
#x %>% f(y) %>% g(z)會轉(zhuǎn)換為g(f(x, y), z)淘这,以此類推颂翼。
#支持管道操作是 tidyverse 中的 R 包的核心原則之一。
#唯一的例外就是 ggplot2:它是在發(fā) 現(xiàn)管道方式前開發(fā)的慨灭。
#ggplot2 的下一個版本 ggvis 支持管道操作朦乏,遺憾的是其還沒有達到成熟完備的程度。
#缺失值
#如果輸入中有缺失值氧骤,那么輸出也會是缺失值呻疹。
#所有聚合函數(shù)都有一個 na.rm 參數(shù),它可以在計算前除去缺失值
#缺失值表示取消的航班筹陵,
flights %>%
group_by(year, month, day) %>%
? summarize(mean = mean(dep_delay, na.rm = TRUE))
#我們也可以通過先去除取消的航班來解決缺失值問題刽锤。
not_cancelled <- flights %>%
? filter(!is.na(dep_delay), !is.na(arr_delay))
not_cancelled %>%
? group_by(year, month, day) %>%
? summarize(mean = mean(dep_delay))
#計數(shù)
#聚合操作中包括一個計數(shù)(n())或非缺失值的計數(shù)(sum(!is_na()))
#確保自己沒有基于非常少量的數(shù)據(jù)作出結(jié)論
#具有最長平均延誤時間的飛機(通過機尾編號進行識別)
delays <- not_cancelled %>%
? group_by(tailnum) %>%
? summarize(
? ? delay = mean(arr_delay)
? )
ggplot(data = delays, mapping = aes(x = delay)) +
? geom_freqpoly(binwidth = 10)
#畫一張航班數(shù)量和平均延誤時間的散點圖
delays <- not_cancelled %>%
? group_by(tailnum) %>%
? summarize(
? ? delay = mean(arr_delay, na.rm = TRUE),
? ? n = n() )
ggplot(data = delays, mapping = aes(x = n, y = delay)) +
? geom_point(alpha = 1/10)
#當(dāng)航班數(shù)量非常少時,平均延誤時間的變動特別大朦佩。
#這張圖的形狀非常能夠說明問題:
#當(dāng)繪制均值(或其他摘要統(tǒng)計量)和分組規(guī)模的關(guān)系時并思,
#你總能看到隨著樣本量的增加,變動在不斷減小语稠。
#通常應(yīng)該篩選掉那些觀測數(shù)量非常少的分組宋彼,
#這樣你就可以避免受到特別小的分組中的極端變動的影響,
#進而更好地發(fā)現(xiàn)數(shù)據(jù)模式仙畦。
#展示了將 ggplot2 集成到 dplyr 工作流中的一種有效方式输涕。
#從 %>% 過渡到 + 會令人感到不適應(yīng),但掌握其中的要領(lǐng)后慨畸,這種寫法是非常方便的:
delays %>%
? filter(n > 25) %>%
? ggplot(mapping = aes(x = n, y = delay)) +
? geom_point(alpha = 1/10)
#棒球擊球手的平均表現(xiàn)與擊球次數(shù)之間的關(guān)系莱坎。
#擊球手的能力(用打擊率 ba 衡量)與擊球機會數(shù)量(用打數(shù) ab 衡量)
batting <- as_tibble(Lahman::Batting) # 轉(zhuǎn)換成tibble,以便輸出更美觀
batters <- batting %>%
? group_by(playerID) %>%
? summarize(
? ? ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),
? ? ab = sum(AB, na.rm = TRUE) )
batters %>%
? filter(ab > 100) %>%
? ggplot(mapping = aes(x = ab, y = ba)) +
? geom_point() +
? geom_smooth(se = FALSE)
#> `geom_smooth()` using method = 'gam'
#常用的摘要函數(shù)
#只使用均值寸士、計數(shù)和求和是遠遠不夠的
#位置度量
#我們已經(jīng)使用過 mean(x)檐什,但 median(x) 也非常有用。
#均值是總數(shù)除以個數(shù);
#中位數(shù)則 是這樣一個值:50% 的 x 大于它弱卡,同時 50% 的 x 小于它乃正。
#有時候需要將聚合函數(shù)和邏輯篩選組合起來使用。
not_cancelled %>%
? group_by(year, month, day) %>%
? summarize(
? ? # 平均延誤時間:
? ? avg_delay1 = mean(arr_delay),
? ? # 平均正延誤時間:
? ? avg_delay2 = mean(arr_delay[arr_delay > 0])
? )
#分散程度度量:sd(x)谐宙、IQR(x) 和 mad(x)
#均方誤差(又稱標準誤差烫葬,standard deviation,sd)是分散程度的標準度量方式。
#四分位距 IQR() 和絕對中位差 mad(x) 基本等價搭综,更適合有離群點的情況:
# 為什么到某些目的地的距離比到其他目的地更多變?
not_cancelled %>%
group_by(dest) %>%
? summarize(distance_sd = sd(distance)) %>%
? arrange(desc(distance_sd))
#秩的度量:min(x)垢箕、quantile(x, 0.25) 和 max(x)
#分位數(shù)是中位數(shù)的擴展。
#例如兑巾,quantile(x, 0.25)會找出x中按從小到大順序大于前 25% 而小于后75% 的值:
# 每天最早和最晚的航班何時出發(fā)?
not_cancelled %>%
group_by(year, month, day) %>%
? summarize(
? ? first = min(dep_time),
? ? last = max(dep_time)
? )
#定位度量:first(x)条获、nth(x, 2) 和 last(x)
#這幾個函數(shù)的作用與 x[1]、x[2] 和 x[length(x)] 相同蒋歌,
#只是當(dāng)定位不存在時(比如嘗試從只有兩個元素的分組中得到第三個元素)帅掘,
#前者允許你設(shè)置一個默認值。
#例如堂油,我們可以找出每天最早和最晚出發(fā)的航班:
not_cancelled %>%
? group_by(year, month, day) %>%
? summarize(
? ? first_dep = first(dep_time),
? ? last_dep = last(dep_time)
? )
#這些函數(shù)對篩選操作進行了排秩方面的補充修档。
#篩選會返回所有變量,每個觀測在單獨的一行中:
not_cancelled %>%
? group_by(year, month, day) %>%
? mutate(r = min_rank(desc(dep_time))) %>%
? filter(r %in% range(r))
#range()返回的是一個向量里面最大值和最小值
#計數(shù)
#你已經(jīng)見過 n()府框,它不需要任何參數(shù)吱窝,并返回當(dāng)前分組的大小。
#計算出非缺失值的數(shù)量迫靖,可以使用 sum(!is.na(x))院峡。
#要想計算出唯一值的數(shù)量,可以使用 n_ distinct(x)
# 哪個目的地具有最多的航空公司?
not_cancelled %>%
group_by(dest) %>%
? summarize(carriers = n_distinct(carrier)) %>%
? arrange(desc(carriers))
#dplyr 提供了一個簡單的輔助函數(shù)系宜,用于只需要計數(shù)的情況:
not_cancelled %>%
? count(dest)
#還可以選擇提供一個加權(quán)變量照激。
#例如,你可以使用以下代碼算出每架飛機飛行的總里程數(shù)(實際上就是求和)
not_cancelled %>%
? count(tailnum, wt = distance)
#邏輯值的計數(shù)和比例:sum(x > 10) 和 mean(y == 0)
#當(dāng)與數(shù)值型函數(shù)一同使用時盹牧,TRUE 會轉(zhuǎn)換為 1俩垃,F(xiàn)ALSE 會轉(zhuǎn)換為 0。
#這使得 sum() 和 mean() 非常適用于邏輯值:
#sum(x) 可以找出 x 中 TRUE 的數(shù)量欢策,mean(x) 則可以找出比例吆寨。
# 多少架航班是在早上5點前出發(fā)的?(這通常表明前一天延誤的航班數(shù)量)
not_cancelled %>%
group_by(year, month, day) %>%
? summarize(n_early = sum(dep_time < 500))
# 延誤超過1小時的航班比例是多少?
not_cancelled %>%
group_by(year, month, day) %>%
? summarize(hour_perc = mean(arr_delay > 60))
#按多個變量分組
#當(dāng)使用多個變量進行分組時赏淌,每次的摘要統(tǒng)計會用掉一個分組變量踩寇。
daily <- group_by(flights, year, month, day)
(per_day <- summarize(daily, flights = n()))
(per_month <- summarize(per_day, flights = sum(flights)))
(per_year <- summarize(per_month, flights = sum(flights)))
#在循序漸進地進行摘要分析時,需要小心:使用求和與計數(shù)操作是沒問題的六水,
#但如果想要 使用加權(quán)平均和方差的話俺孙,就要仔細考慮一下,
#在基于秩的統(tǒng)計數(shù)據(jù)(如中位數(shù))上是無法進行這些操作的掷贾。
#換句話說睛榄,對分組求和的結(jié)果再求和就是對整體求和,
#但分組中位數(shù)的中位數(shù)可不是整體的中位數(shù)想帅。
#取消分組
#如果想要取消分組场靴,并回到未分組的數(shù)據(jù)繼續(xù)操作,
#那么可以使用 ungroup() 函數(shù):
daily %>%
? ungroup() %>% # 不再按日期分組
? summarize(flights = n()) # 所有航班
#這些函數(shù)都可以和 group_by() 函數(shù)聯(lián)合起來使用,
#group_by() 函數(shù)可以改變以上每個函數(shù)的作用范圍旨剥,
#讓其從在整個數(shù)據(jù)集上操作變?yōu)樵诿總€分組上分別操作咧欣。
#一架航班 50% 的時間會提前 15 分鐘,50% 的時間會延誤 15 分鐘轨帜。
not_cancelled %>%
group_by(tailnum) %>%
summarise(delay_perc1=mean(dep_delay==-15),delay_perc2=mean(arr_delay==-15))%>%
? filter(delay_perc1==0.5,delay_perc2==0.5)
#分組新變量(和篩選器)
#雖然與 summarize() 函數(shù)結(jié)合起來使用是最有效的魄咕,
#但分組也可以與 mutate() 和 filter()函數(shù)結(jié)合,以完成非常便捷的操作蚌父。
#找出每個分組中最差的成員:
flights_sml %>%
? group_by(year, month, day) %>%
? filter(rank(desc(arr_delay)) < 10)
#找出大于某個閾值的所有分組:
? popular_dests <- flights %>%
? group_by(dest) %>%
? filter(n() > 365)
popular_dests
#對數(shù)據(jù)進行標準化以計算分組指標:
popular_dests %>%
? filter(arr_delay > 0) %>%
? mutate(prop_delay = arr_delay / sum(arr_delay)) %>%
? select(year:day, dest, arr_delay, prop_delay)