查看原文
其他

R数据科学|3.5内容介绍及习题解答

我才是赵西西 庄闪闪的R语言手册 2023-05-11

上节我们对选择现有的列进行了介绍与习题解答,现在对数据框添加新列进行介绍,这里使用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(122NA34)
min_rank(y)
#> [1] 1 2 2 NA 4 5
min_rank(desc(y))
#> [1] 5 3 3 NA 2 1

习题解答

接下来对该节的课后习题进行解答,结果仅供参考,有疑问的欢迎文末留言,一起交流。

问题一

虽然现在的dep_timesched_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_timearr_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))
> [1327150

结果是,有许多航班的air_time != arr_time - dep_time。除了数据错误,我可以想到两个原因。有些航班午夜出发,因此是arr_time < dep_time。在这种情况下,时间的差异应该是24小时(1,440分钟)。有些航班跨越时区,总飞行时间将以小时(60的倍数)为间隔。所有航班都是从纽约起飞的,都是美国国内航班。这意味着所有航班都将飞往相同或更西风的时区。考虑到美国的时区,时区差异应该是60分钟(中部),120分钟(山区),180分钟(太平洋),240分钟(阿拉斯加),或300分钟(夏威夷)。

问题三

比较dep_timesched_dep_timedep_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))
  > [11236

问题四

使用排秩函数找出 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会将较短向量的值,生成与较长向量相同长度的向量。该代码还发出一个警告,即较短的向量不是较长向量的倍数。当发生这种情况时,会发出警告,因为这通常是无意的,可能是错误。


往期推荐


R数据科学|3.3课后习题

R数据科学|3.2.4课后习题

[R数据科学]tidyverse数据清洗案例详解

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存