查看原文
其他

21 天从入门到精通 R 语言|使用 R 语言进行数据处理(一)

RStata RStata 2023-10-24

为了让大家更好的理解本文的内容,欢迎各位培训班会员参加明天晚上 9 点的直播课:「使用 R 语言进行数据处理(一)」

该课程是「R 语言数据科学的第 4 课时」,课程主页(点击文末的阅读原文即可跳转):

https://rstata.duanshu.com/#/brief/course/229b770183e44fbbb64133df929818ec


本次课程将细致的讲解使用 R 语言处理数据的各种操作。

使用 R 语言作为计算器

1 / 200 * 30
#> [1] 0.15
(59 + 73 + 2) / 3
#> [1] 44.66667
sin(pi / 2)
#> [1] 1

但是上面的结果都是直接被打印了出来,不能再次调用,因此我们需要将他们保存起来,最快速的方式就是保存为对象,因此我们要首先了解 R 语言中对象的命名规则:

实际上没有规则,只要你能记得每次使用对象的时候都用 ` 把它括起来,那你几乎可以使用任意形式的对象名称,甚至:

`1` <- 1
`a b` <- 2
`1` + `a b`
#> [1] 3

不过尽管如此,建议你遵循下列规则:

  1. 不能包含空格;
  2. 不能包含运算符,例如 -, +, *, /
  3. 不能包含 ., ?
  4. 不能以数字开头;
  5. 大小写敏感;
  6. 建议不要使用中文变量名,变量名不宜使用 a, b, c 这种缺乏实际含义的字符,可以使用简单的英文或英文缩写。例如 pop 之类的。

数据操作:dplyr 包的使用

在下面的案例中我们将使用 flights 数据集演示:

nycflights13::flights -> flights
flights
#> # A tibble: 336,776 × 19
#>     year month   day dep_time sched_de…¹ dep_d…² arr_t…³ sched…⁴ arr_d…⁵ carrier
#>    <int> <int> <int>    <int>      <int>   <dbl>   <int>   <int>   <dbl> <chr>  
#>  1  2013     1     1      517        515       2     830     819      11 UA     
#>  2  2013     1     1      533        529       4     850     830      20 UA     
#>  3  2013     1     1      542        540       2     923     850      33 AA     
#>  4  2013     1     1      544        545      -1    1004    1022     -18 B6     
#>  5  2013     1     1      554        600      -6     812     837     -25 DL     
#>  6  2013     1     1      554        558      -4     740     728      12 UA     
#>  7  2013     1     1      555        600      -5     913     854      19 B6     
#>  8  2013     1     1      557        600      -3     709     723     -14 EV     
#>  9  2013     1     1      557        600      -3     838     846      -8 B6     
#> 10  2013     1     1      558        600      -2     753     745       8 AA     
#> # … with 336,766 more rows, 9 more variables: flight <int>, tailnum <chr>,
#> #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#> #   minute <dbl>, time_hour <dttm>, and abbreviated variable names
#> #   ¹sched_dep_time, ²dep_delay, ³arr_time, ⁴sched_arr_time, ⁵arr_delay

filter 函数

由于包导入顺序的问题,在我电脑上,stats 包的 filter 函数覆盖了 dplyr 包的 filter 函数,所以在下面的操作中我将使用 dplyr::filter 表示使用 dplyr 包的 filter 函数:

library(tidyverse)
dplyr::filter
#> function (.data, ..., .by = NULL, .preserve = FALSE) 
#> {
#>     check_by_typo(...)
#>     by <- enquo(.by)
#>     if (!quo_is_null(by) && !is_false(.preserve)) {
#>         abort("Can't supply both `.by` and `.preserve`.")
#>     }
#>     UseMethod("filter")
#> }
#> <bytecode: 0x7fee4dea13d8>
#> <environment: namespace:dplyr>

顾名思义,filter 函数的功能是用于行筛选,例如我们选择出所有 1 月 1 日的航班:

dplyr::filter(flights, month == 1, day == 1)
#> # A tibble: 842 × 19
#>     year month   day dep_time sched_de…¹ dep_d…² arr_t…³ sched…⁴ arr_d…⁵ carrier
#>    <int> <int> <int>    <int>      <int>   <dbl>   <int>   <int>   <dbl> <chr>  
#>  1  2013     1     1      517        515       2     830     819      11 UA     
#>  2  2013     1     1      533        529       4     850     830      20 UA     
#>  3  2013     1     1      542        540       2     923     850      33 AA     
#>  4  2013     1     1      544        545      -1    1004    1022     -18 B6     
#>  5  2013     1     1      554        600      -6     812     837     -25 DL     
#>  6  2013     1     1      554        558      -4     740     728      12 UA     
#>  7  2013     1     1      555        600      -5     913     854      19 B6     
#>  8  2013     1     1      557        600      -3     709     723     -14 EV     
#>  9  2013     1     1      557        600      -3     838     846      -8 B6     
#> 10  2013     1     1      558        600      -2     753     745       8 AA     
#> # … with 832 more rows, 9 more variables: flight <int>, tailnum <chr>,
#> #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#> #   minute <dbl>, time_hour <dttm>, and abbreviated variable names
#> #   ¹sched_dep_time, ²dep_delay, ³arr_time, ⁴sched_arr_time, ⁵arr_delay

更多的时候我会使用管道操作符,下面的操作和上面的操作功能一样:

flights %>% 
  dplyr::filter(month == 1, day == 1)
#> # A tibble: 842 × 19
#>     year month   day dep_time sched_de…¹ dep_d…² arr_t…³ sched…⁴ arr_d…⁵ carrier
#>    <int> <int> <int>    <int>      <int>   <dbl>   <int>   <int>   <dbl> <chr>  
#>  1  2013     1     1      517        515       2     830     819      11 UA     
#>  2  2013     1     1      533        529       4     850     830      20 UA     
#>  3  2013     1     1      542        540       2     923     850      33 AA     
#>  4  2013     1     1      544        545      -1    1004    1022     -18 B6     
#>  5  2013     1     1      554        600      -6     812     837     -25 DL     
#>  6  2013     1     1      554        558      -4     740     728      12 UA     
#>  7  2013     1     1      555        600      -5     913     854      19 B6     
#>  8  2013     1     1      557        600      -3     709     723     -14 EV     
#>  9  2013     1     1      557        600      -3     838     846      -8 B6     
#> 10  2013     1     1      558        600      -2     753     745       8 AA     
#> # … with 832 more rows, 9 more variables: flight <int>, tailnum <chr>,
#> #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#> #   minute <dbl>, time_hour <dttm>, and abbreviated variable names
#> #   ¹sched_dep_time, ²dep_delay, ³arr_time, ⁴sched_arr_time, ⁵arr_delay

但是这样只会把筛选结果打印出来,如果你在后面的代码中使用这个结果,你需要把它保存起来:

flights %>% 
  dplyr::filter(month == 1, day == 1) -> jan1

思考:dplyr::filter 函数使用逻辑表达式(与或非)进行筛选,尝试进行更多的筛选。

flights %>% 
  dplyr::filter(month == 1 | day == 1)
flights %>% 
  dplyr::filter(month == 1 & day == 1)
flights %>% 
  dplyr::filter(month != 1, day != 1)
flights %>% 
  dplyr::filter(month >= 1, day != 1)
flights %>% 
  dplyr::filter(month == 11 | month == 12)
flights %>% 
  dplyr::filter(month %in% c(1112))
flights %>% 
  dplyr::filter(!month %in1:10)

需要注意的是 ==, >=, > 等运算符号进行的是精确筛选,由于精度的问题,可能会产生下列错误:

sqrt(2) ^ 2 == 2
#> [1] FALSE
1 / 49 * 49 == 1
#> [1] FALSE

这个时候我们可以使用 near 函数进行模糊比较:

near(sqrt(2) ^ 2,  2)
#> [1] TRUE
near(1 / 49 * 491)
#> [1] TRUE

说到逻辑表达式,R 语言里面有一类非常值得关注的函数 is.*,例如 is.na:

tibble(
  x = c(1NA2),
  y = c(21NA)
) -> df
df %>% 
  dplyr::filter(is.na(x))
#> # A tibble: 1 × 2
#>       x     y
#>   <dbl> <dbl>
#> 1    NA     1

df %>% 
  dplyr::filter(!is.na(x))
#> # A tibble: 2 × 2
#>       x     y
#>   <dbl> <dbl>
#> 1     1     2
#> 2     2    NA

df %>% 
  dplyr::filter(across(everything(), ~!is.na(.x)))
#> # A tibble: 1 × 2
#>       x     y
#>   <dbl> <dbl>
#> 1     1     2

# 等价于
df %>% 
  dplyr::filter(if_all(everything(), ~!is.na(.x)))
#> # A tibble: 1 × 2
#>       x     y
#>   <dbl> <dbl>
#> 1     1     2

需要注意,缺失值不能使用 == 运算:

x <- NA
y <- NA
x == y
#> [1] NA
identical(x, y)
#> [1] TRUE
x == NA
#> [1] NA
is.na(x)
#> [1] TRUE

补充学习:

dplyr::filter 还有三个衍生函数,非常好用:filter_all, filter_at 和 filter_if,不过这三个函数已经废弃了(未来不会再有新功能了),现在更建议组合使用 filter 和 across/if_all/if_any 函数:

例如我们筛选出 mtcars 数据集中所有变量都大于 150 的观测值:

as_tibble(mtcars) -> mtcars
filter_all(mtcars, all_vars(. > 150))
#> # A tibble: 0 × 11
#> # … with 11 variables: mpg <dbl>, cyl <dbl>, disp <dbl>, hp <dbl>, drat <dbl>,
#> #   wt <dbl>, qsec <dbl>, vs <dbl>, am <dbl>, gear <dbl>, carb <dbl>
# 等价于:
dplyr::filter(mtcars, across(everything(), ~ .x > 150))
# 等价于
dplyr::filter(mtcars, if_all(everything(), ~ .x > 150))

结果没有一个观测值满足条件,那我们再筛选出某个变量大于 150 的观测值:

filter_all(mtcars, any_vars(. > 150))
#> # A tibble: 21 × 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  4  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  5  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  6  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  7  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#>  8  17.8     6  168.   123  3.92  3.44  18.9     1     0     4     4
#>  9  16.4     8  276.   180  3.07  4.07  17.4     0     0     3     3
#> 10  17.3     8  276.   180  3.07  3.73  17.6     0     0     3     3
#> # … with 11 more rows

# 等价于
rowAny <- function(x) rowSums(x) > 0
dplyr::filter(mtcars, rowAny(across(where(is.numeric), ~ .x > 150)))

# 等价于
dplyr::filter(mtcars, if_any(where(is.numeric), ~ .x > 150))

如果我们想筛选出所有以 d 开头的变量,且这些变量中的某个变量的值为偶数,我们就需要用 filter_at 函数了:

filter_at(mtcars, vars(starts_with("d")),
          any_vars((. %% 2) == 0))
#> # A tibble: 13 × 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6   160   110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
#>  3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
#>  4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
#>  5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
#>  6  14.3     8   360   245  3.21  3.57  15.8     0     0     3     4
#>  7  10.4     8   472   205  2.93  5.25  18.0     0     0     3     4
#>  8  10.4     8   460   215  3     5.42  17.8     0     0     3     4
#>  9  14.7     8   440   230  3.23  5.34  17.4     0     0     3     4
#> 10  15.5     8   318   150  2.76  3.52  16.9     0     0     3     2
#> 11  15.2     8   304   150  3.15  3.44  17.3     0     0     3     2
#> 12  13.3     8   350   245  3.73  3.84  15.4     0     0     3     4
#> 13  19.2     8   400   175  3.08  3.84  17.0     0     0     3     2

# 等价于
dplyr::filter(mtcars, rowAny(across(c(starts_with("d")), ~ .x %% 2 == 0)))

# 等价于
dplyr::filter(mtcars, if_any(starts_with("d"), ~ .x %% 2 == 0))

filter_if 函数则可对符合某一条件的变量进行筛选,例如筛选所有数值型变量不等于0的观测值:

filter_if(mtcars, ~is.numeric(.), all_vars(. != 0))
#> # A tibble: 7 × 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1  22.8     4 108      93  3.85  2.32  18.6     1     1     4     1
#> 2  32.4     4  78.7    66  4.08  2.2   19.5     1     1     4     1
#> 3  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
#> 4  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
#> 5  27.3     4  79      66  4.08  1.94  18.9     1     1     4     1
#> 6  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
#> 7  21.4     4 121     109  4.11  2.78  18.6     1     1     4     2

# 等价于
dplyr::filter(mtcars, across(where(is.numeric), ~ .x != 0))

# 等价于
dplyr::filter(mtcars, if_all(where(is.numeric), ~ .x != 0))

帮助文档中还给出了一个例子,大家看看是什么意思:

filter_if(mtcars, ~ all(floor(.) == .), all_vars(. != 0))
#> # A tibble: 7 × 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1  22.8     4 108      93  3.85  2.32  18.6     1     1     4     1
#> 2  32.4     4  78.7    66  4.08  2.2   19.5     1     1     4     1
#> 3  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
#> 4  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
#> 5  27.3     4  79      66  4.08  1.94  18.9     1     1     4     1
#> 6  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
#> 7  21.4     4 121     109  4.11  2.78  18.6     1     1     4     2

# 等价于
is_int <- function(x) all(floor(x) == x)
dplyr::filter(mtcars, across(where(is_int), ~ .x != 0))

# 等价于
dplyr::filter(mtcars, if_all(where(is_int), ~ .x != 0))

arrange 函数

arrange 函数可以用于观测值排序,例如:

arrange(flights, year, month, day)
#> # A tibble: 336,776 × 19
#>     year month   day dep_time sched_de…¹ dep_d…² arr_t…³ sched…⁴ arr_d…⁵ carrier
#>    <int> <int> <int>    <int>      <int>   <dbl>   <int>   <int>   <dbl> <chr>  
#>  1  2013     1     1      517        515       2     830     819      11 UA     
#>  2  2013     1     1      533        529       4     850     830      20 UA     
#>  3  2013     1     1      542        540       2     923     850      33 AA     
#>  4  2013     1     1      544        545      -1    1004    1022     -18 B6     
#>  5  2013     1     1      554        600      -6     812     837     -25 DL     
#>  6  2013     1     1      554        558      -4     740     728      12 UA     
#>  7  2013     1     1      555        600      -5     913     854      19 B6     
#>  8  2013     1     1      557        600      -3     709     723     -14 EV     
#>  9  2013     1     1      557        600      -3     838     846      -8 B6     
#> 10  2013     1     1      558        600      -2     753     745       8 AA     
#> # … with 336,766 more rows, 9 more variables: flight <int>, tailnum <chr>,
#> #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#> #   minute <dbl>, time_hour <dttm>, and abbreviated variable names
#> #   ¹sched_dep_time, ²dep_delay, ³arr_time, ⁴sched_arr_time, ⁵arr_delay

arrange(flights, desc(dep_delay))
#> # A tibble: 336,776 × 19
#>     year month   day dep_time sched_de…¹ dep_d…² arr_t…³ sched…⁴ arr_d…⁵ carrier
#>    <int> <int> <int>    <int>      <int>   <dbl>   <int>   <int>   <dbl> <chr>  
#>  1  2013     1     9      641        900    1301    1242    1530    1272 HA     
#>  2  2013     6    15     1432       1935    1137    1607    2120    1127 MQ     
#>  3  2013     1    10     1121       1635    1126    1239    1810    1109 MQ     
#>  4  2013     9    20     1139       1845    1014    1457    2210    1007 AA     
#>  5  2013     7    22      845       1600    1005    1044    1815     989 MQ     
#>  6  2013     4    10     1100       1900     960    1342    2211     931 DL     
#>  7  2013     3    17     2321        810     911     135    1020     915 DL     
#>  8  2013     6    27      959       1900     899    1236    2226     850 DL     
#>  9  2013     7    22     2257        759     898     121    1026     895 DL     
#> 10  2013    12     5      756       1700     896    1058    2020     878 AA     
#> # … with 336,766 more rows, 9 more variables: flight <int>, tailnum <chr>,
#> #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#> #   minute <dbl>, time_hour <dttm>, and abbreviated variable names
#> #   ¹sched_dep_time, ²dep_delay, ³arr_time, ⁴sched_arr_time, ⁵arr_delay

排序的时候就要注意缺失值的位置了:

df <- tibble(x = c(52NA))
arrange(df, x)
#> # A tibble: 3 × 1
#>       x
#>   <dbl>
#> 1     2
#> 2     5
#> 3    NA
arrange(df, desc(x))
#> # A tibble: 3 × 1
#>       x
#>   <dbl>
#> 1     5
#> 2     2
#> 3    NA

可以看到,不管怎么样,缺失值总是会被排在最后。那么如果我们想把缺失值排在前面怎么做呢?

arrange(df, desc(is.na(x)), x)
#> # A tibble: 3 × 1
#>       x
#>   <dbl>
#> 1    NA
#> 2     2
#> 3     5

看起来很懵,实际上它是借助一个新的变量进行排序的:

df %>% 
  mutate(
    newx = desc(is.na(x))
  ) %>% 
  arrange(newx, x) %>% 
  select(-newx)
#> # A tibble: 3 × 1
#>       x
#>   <dbl>
#> 1    NA
#> 2     2
#> 3     5

select 函数

select 函数可以用于列的选择(变量筛选):

select(flights, year, month, day)
#> # A tibble: 336,776 × 3
#>     year month   day
#>    <int> <int> <int>
#>  1  2013     1     1
#>  2  2013     1     1
#>  3  2013     1     1
#>  4  2013     1     1
#>  5  2013     1     1
#>  6  2013     1     1
#>  7  2013     1     1
#>  8  2013     1     1
#>  9  2013     1     1
#> 10  2013     1     1
#> # … with 336,766 more rows

select(flights, year:day)
select(flights, -(year:day))
select(flights, starts_with("y"))
select(flights, ends_with("r"))
select(flights, contains("ye"))
select(flights, matches("y(.*)r"))

tibble(
  x1 = 1:3,
  x2 = 2:4,
  x3 = 4:6
) %>% 
  select(num_range("x"1:2))
#> # A tibble: 3 × 2
#>      x1    x2
#>   <int> <int>
#> 1     1     2
#> 2     2     3
#> 3     3     4

select 函数还可以用于变量的重命名:

flights %>% 
  select(y = year)
flights %>% 
  select(year) %>% 
  rename(y = year)

select 函数也有三个非常好用的衍生函数:select_all, select_if, select_at,不过同样这些函数都被废弃了,建议使用 select/rename_with/where 函数:

例如选择所有的数值型变量:

select_if(mtcars, is.numeric)
#> # A tibble: 32 × 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # … with 22 more rows

# 等价于
select(mtcars, where(is.numeric))

例如将所有变量名不包含 "ar" 或 "c" 开头的变量重命名为其大写形式:

mtcars %>% 
  select_at(vars(!contains("ar"), starts_with("c")), toupper)
#> # A tibble: 32 × 10
#>      MPG   CYL  DISP    HP  DRAT    WT  QSEC    VS    AM  CARB
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     2
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     4
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     2
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     2
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
#> # … with 22 more rows

# 等价于
mtcars %>%
  select(!contains("ar") | starts_with("c")) %>%
  rename_with(toupper)

再例如,将所有的变量重命名为其大写形式:

mtcars %>% 
  select_all(toupper)
#> # A tibble: 32 × 11
#>      MPG   CYL  DISP    HP  DRAT    WT  QSEC    VS    AM  GEAR  CARB
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # … with 22 more rows

# 等价于
mtcars %>%
  rename_with(toupper)

mutate 函数

mutate 函数的功能是对数据框的变量进行修改或者添加新列:

flights %>% 
  select(year:day, ends_with("delay"), 
         distance, air_time) -> flights_sml

flights_sml %>% 
  mutate(gain = dep_delay - arr_delay,
         speed = distance / air_time * 60)
#> # A tibble: 336,776 × 9
#>     year month   day dep_delay arr_delay distance air_time  gain speed
#>    <int> <int> <int>     <dbl>     <dbl>    <dbl>    <dbl> <dbl> <dbl>
#>  1  2013     1     1         2        11     1400      227    -9  370.
#>  2  2013     1     1         4        20     1416      227   -16  374.
#>  3  2013     1     1         2        33     1089      160   -31  408.
#>  4  2013     1     1        -1       -18     1576      183    17  517.
#>  5  2013     1     1        -6       -25      762      116    19  394.
#>  6  2013     1     1        -4        12      719      150   -16  288.
#>  7  2013     1     1        -5        19     1065      158   -24  404.
#>  8  2013     1     1        -3       -14      229       53    11  259.
#>  9  2013     1     1        -3        -8      944      140     5  405.
#> 10  2013     1     1        -2         8      733      138   -10  319.
#> # … with 336,766 more rows

flights_sml %>% 
  mutate(gain = dep_delay - arr_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  gain hours gain_pe…¹
#>    <int> <int> <int>     <dbl>     <dbl>    <dbl>    <dbl> <dbl> <dbl>     <dbl>
#>  1  2013     1     1         2        11     1400      227    -9 3.78      -2.38
#>  2  2013     1     1         4        20     1416      227   -16 3.78      -4.23
#>  3  2013     1     1         2        33     1089      160   -31 2.67     -11.6 
#>  4  2013     1     1        -1       -18     1576      183    17 3.05       5.57
#>  5  2013     1     1        -6       -25      762      116    19 1.93       9.83
#>  6  2013     1     1        -4        12      719      150   -16 2.5       -6.4 
#>  7  2013     1     1        -5        19     1065      158   -24 2.63      -9.11
#>  8  2013     1     1        -3       -14      229       53    11 0.883     12.5 
#>  9  2013     1     1        -3        -8      944      140     5 2.33       2.14
#> 10  2013     1     1        -2         8      733      138   -10 2.3       -4.35
#> # … with 336,766 more rows, and abbreviated variable name ¹gain_per_hour

如果你只想保留修改或新增的列,可以使用 transmute 函数:

flights %>% 
  transmute(gain = dep_delay - arr_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.6 
#>  4    17 3.05           5.57
#>  5    19 1.93           9.83
#>  6   -16 2.5           -6.4 
#>  7   -24 2.63          -9.11
#>  8    11 0.883         12.5 
#>  9     5 2.33           2.14
#> 10   -10 2.3           -4.35
#> # … with 336,766 more rows

同样 mutate 也有 mutate_all, mutate_at 和 mutate_if 三个衍生函数,同样。。。也都被废弃了,更建议使用 across 和 mutate 的组合:

例如计算所有数值型变量的均值:

tibble(x = 1:3, y = 3:5, z = 5:7) -> df
df %>% 
  mutate_if(is.numeric, mean, na.rm = T)
#> # A tibble: 3 × 3
#>       x     y     z
#>   <dbl> <dbl> <dbl>
#> 1     2     4     6
#> 2     2     4     6
#> 3     2     4     6

# 等价于
df %>% 
  mutate(across(where(is.numeric), mean, na.rm = TRUE))

计算 x 和以 y 开头的变量的均值:

df %>% 
  mutate_at(vars(c(x, starts_with("y"))), mean)
#> # A tibble: 3 × 3
#>       x     y     z
#>   <dbl> <dbl> <int>
#> 1     2     4     5
#> 2     2     4     6
#> 3     2     4     7

# 等价于
df %>% 
  mutate(across(c(x, starts_with("y")), mean, na.rm = TRUE))

计算所有变量的均值:

df %>% 
  mutate_all(mean)
#> # A tibble: 3 × 3
#>       x     y     z
#>   <dbl> <dbl> <dbl>
#> 1     2     4     6
#> 2     2     4     6
#> 3     2     4     6

# 等价于
df %>% 
  mutate(across(everything(), mean))

常用的函数

  1. +, -, *, /, ^, %/%(整除), %%(求余);
  2. log(), log2(), log10();
  3. lag(), lead(), diff();
  4. cumsum(), cumprod(), cummin(), cummax(), cummean();
  5. ==, >=, >, <, <=, !=;
  6. 排名函数:
y <- c(122NA34)
min_rank(y)
#> [1]  1  2  2 NA  4  5
min_rank(desc(y))
#> [1]  5  3  3 NA  2  1
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

因为时间关系,第一部分就先到这里了~

直播信息

为了让大家更好的理解上面的内容,欢迎各位培训班会员参加明天晚上 9 点的直播课:「使用 R 语言进行数据处理(一)」

  1. 直播地址:腾讯会议(需要报名 RStata 培训班参加)
  2. 讲义材料:需要报名 RStata 培训班,详情可阅读:一起来学习 R 语言和 Stata 啦!学习过程中遇到的问题也可以随时提问!

更多关于 RStata 会员的更多信息可添加微信号 r_stata 咨询:


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

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