R数据科学|3.5内容介绍及习题解答
上节我们对选择现有的列进行了介绍与习题解答,现在对数据框添加新列进行介绍,这里使用mutate()
函数,注意:mutate()
总是将新列添加在数据集的最后。
mutate(flights_sml,
gain = arr_delay - dep_delay,
hours = air_time / 60,
gain_per_hour = gain / hours
)
#> # A tibble: 336,776 × 10
#> year month day dep_delay arr_delay distance air_time
#> <int> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 2013 1 1 2 11 1400 227
#> 2 2013 1 1 4 20 1416 227
#> 3 2013 1 1 2 33 1089 160
#> 4 2013 1 1 -1 -18 1576 183
#> 5 2013 1 1 -6 -25 762 116
#> 6 2013 1 1 -4 12 719 150
#> # ... with 3.368e+05 more rows, and 3 more variables:
#> # gain <dbl>, hours <dbl>, gain_per_hour <dbl>
如果只想保留新变量,可以使用transmute()
函数:
transmute(flights,
gain = arr_delay - dep_delay,
hours = air_time / 60,
gain_per_hour = gain / hours
)
#> # A tibble: 336,776 × 3
#> gain hours gain_per_hour
#> <dbl> <dbl> <dbl>
#> 1 9 3.78 2.38
#> 2 16 3.78 4.23
#> 3 31 2.67 11.62
#> 4 -17 3.05 -5.57
#> 5 -19 1.93 -9.83
#> 6 16 2.50 6.40
#> # ... with 3.368e+05 more rows
常用创建函数
创建新变量的多种函数可供你同mutate()
一同使用。最重要的一点是,这种函数必须是向量化的;它必须接受一个向量作为输入,并返回一个向量作为输出,而且输入向量与输出向量具有同样数目的分量。下面介绍一些比较常用的创建函数:
算术运算符:+、-、*、/、^
它们都是向量化的,使用所谓的“循环法则”。如果一个参数比另一个参数短,那么前 者会自动扩展到同样的长度。当某个参数是单个数值时,这种方式是最有效的:air_ time / 60、hours * 60 + minute 等。模运算符:%/%和 %%
%/%(整数除法)和 %%(求余)满足 x == y * (x %/% y) + (x %% y)。模运算非常好 用,因为它可以拆分整数。例如,在航班数据集中,你可以根据 dep_time 计算出 hour 和 minute:
transmute(flights,
dep_time,
hour = dep_time %/% 100,
minute = dep_time %% 100
)
#> # A tibble: 336,776 × 3
#> dep_time hour minute
#> <int> <dbl> <dbl>
#> 1 517 5 17
#> 2 533 5 33
#> 3 542 5 42
#> 4 544 5 44
#> 5 554 5 54
#> 6 554 5 54
#> # ... with 3.368e+05 more rows
对数函数:
log()
、log2()
和log10()
在处理取值范围横跨多个数量级的数据时,对数是特别有用的一种转换方式。它还可以将乘法转换成加法。其他条件相同的情况下,更推荐使用log2()
函数,因为很容易对其进行解释:对数标度的数值增加 1 个单位,意味着初始数值加倍;减少 1 个单位,则意味着初始数值减半。偏移函数:
lead()
和lag()
函数
它们可以返回一个序列的领先值和滞后值。它们可以计算出序列的移动 差值(如)或发现序列何时发生了变化。它们与group_by()
组合使用时特别有用。
(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提供了计算累加和、累加积、累加最小值和累加最大值的函数cumsum()
、cumprod()
、commin()
和cummax()
;dplyr 还提供了cummean()
函数以计算累加均值。逻辑比较:<、<=、>、>= 和 !=
如果需要进行一系列复杂的逻辑运算,那么最好将中间结果保存在新变量中,这样就可 以检查是否每一步都符合预期。排秩
min_rank()
可以完成最常用的排秩任务(如第一、第二、第三、第四)。默认的排秩方式是,最小的值获得最前面的名次,使用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
习题解答
接下来对该节的课后习题进行解答,结果仅供参考,有疑问的欢迎文末留言,一起交流。
问题一
虽然现在的dep_time
和sched_dep_time
变量方便阅读,但不适合计算,因为它们实际上并不是连续型数值。将它们转换成一种更方便的表示形式,即从午夜开始的分钟数。
解答
time2mins <- function(x) {
(x %/% 100 * 60 + x %% 100) %% 1440
}
flights_times <- mutate(flights,
dep_time_mins = time2mins(dep_time),
sched_dep_time_mins = time2mins(sched_dep_time)
)
问题二
比较air_time
和 arr_time – dep_time
。你期望看到什么?实际又看到了什么?如何解决这个问题?
解答
预想结果:air_time
是到达时间(arr_time
)和出发时间(dep_time
)之间的差值。检查这种预想是否正确:
flights_airtime <-
mutate(flights,
dep_time = (dep_time %/% 100 * 60 + dep_time %% 100) %% 1440,
arr_time = (arr_time %/% 100 * 60 + arr_time %% 100) %% 1440,
air_time_diff = air_time - arr_time + dep_time
)
nrow(filter(flights_airtime, air_time_diff != 0))
> [1] 327150
结果是,有许多航班的air_time != arr_time - dep_time。除了数据错误,我可以想到两个原因。有些航班午夜出发,因此是arr_time < dep_time。在这种情况下,时间的差异应该是24小时(1,440分钟)。有些航班跨越时区,总飞行时间将以小时(60的倍数)为间隔。所有航班都是从纽约起飞的,都是美国国内航班。这意味着所有航班都将飞往相同或更西风的时区。考虑到美国的时区,时区差异应该是60分钟(中部),120分钟(山区),180分钟(太平洋),240分钟(阿拉斯加),或300分钟(夏威夷)。
问题三
比较dep_time
、sched_dep_time
和 dep_delay
。你期望这3个数值之间具有何种关系?
解答
预想结果:出发延迟(dep_delay
)等于计划出发时间(sched_dep_time
)和实际出发时间(dep_time
)之间的差。下面检查这种假设是否正确:
flights_deptime <-
mutate(flights,
dep_time_min = (dep_time %/% 100 * 60 + dep_time %% 100) %% 1440,
sched_dep_time_min = (sched_dep_time %/% 100 * 60 +
sched_dep_time %% 100) %% 1440,
dep_delay_diff = dep_delay - dep_time_min + sched_dep_time_min
)
nrow(filter(flights_deptime, dep_delay_diff != 0))
> [1] 1236
问题四
使用排秩函数找出 10 个延误时间最长的航班。如何处理名次相同的情况?仔细阅读min_rank() 的帮助文件。
解答
flights_delayed <- mutate(flights, dep_delay_min_rank = min_rank(desc(dep_delay)), dep_delay_row_number = row_number(desc(dep_delay)),dep_delay_dense_rank = dense_rank(desc(dep_delay)))
flights_delayed <- filter(flights_delayed,!(dep_delay_min_rank > 10 | dep_delay_row_number > 10 |dep_delay_dense_rank > 10))
flights_delayed <- arrange(flights_delayed, dep_delay_min_rank)
print(select(flights_delayed, month, day, carrier, flight, dep_delay,dep_delay_min_rank, dep_delay_row_number, dep_delay_dense_rank),n = Inf)
问题五
1:3 + 1:10 会返回什么?为什么?
解答
1:3 + 1:10
#> Warning in 1:3 + 1:10: longer object length is not a multiple of shorter object
#> length
#> [1] 2 4 6 5 7 9 8 10 12 11
当两个向量相加时,R会将较短向量的值,生成与较长向量相同长度的向量。该代码还发出一个警告,即较短的向量不是较长向量的倍数。当发生这种情况时,会发出警告,因为这通常是无意的,可能是错误。
往期推荐