2.3 常用函数

本小节介绍dplyr处理数据时常用的函数,类似sql中的case_when、count、distinct、row_number、between等函数。

2.3.1 条件判断

dplyr::if_else()相比于base::ifelse,if_else输出类型更为严格,无论TRUEFALSE输出类型一致,这样计算速度更快。

dplyr::if_else()参数:

if_else(condition, true, false, missing = NULL)
x <- sample(1:10,5)
if_else(x>5,"大于五","小于等于五",missing = "空值")
#> [1] "大于五"     "大于五"     "大于五"     "大于五"     "小于等于五"

ifelse不同的是,if_else保留类型

x <- factor(sample(letters[1:5], 10, replace = TRUE))
ifelse(x %in% c("a", "b", "c"), x, factor(NA))
#>  [1] NA  2  1 NA  1  2  3  1  1  2
if_else(x %in% c("a", "b", "c"), x, factor(NA))
#>  [1] <NA> b    a    <NA> a    b    c    a    a    b   
#> Levels: a b c d e

data.table::fifelse()功能相似

2.3.2 case_when

当条件嵌套较多时,使用case_when,使代码可读并且不易出错。与sql 中的case when 等价。

x <- 1:50
case_when(
  x %% 35 == 0 ~ "fizz buzz",
  x %% 5 == 0 ~ "fizz",
  x %% 7 == 0 ~ "buzz",
  TRUE ~ as.character(x)
)
#>  [1] "1"         "2"         "3"         "4"         "fizz"      "6"        
#>  [7] "buzz"      "8"         "9"         "fizz"      "11"        "12"       
#> [13] "13"        "buzz"      "fizz"      "16"        "17"        "18"       
#> [19] "19"        "fizz"      "buzz"      "22"        "23"        "24"       
#> [25] "fizz"      "26"        "27"        "buzz"      "29"        "fizz"     
#> [31] "31"        "32"        "33"        "34"        "fizz buzz" "36"       
#> [37] "37"        "38"        "39"        "fizz"      "41"        "buzz"     
#> [43] "43"        "44"        "fizz"      "46"        "47"        "48"       
#> [49] "buzz"      "fizz"
Dates <- as.Date(c('2018-10-01', '2018-10-02', '2018-10-03','2018-10-04'))
case_when(
  Dates == '2018-10-01' ~ Dates - 1,
  Dates == '2018-10-02' ~ Dates + 1,
  Dates == '2018-10-03' ~ Dates + 2,
  TRUE ~ Dates
)
#> [1] "2018-09-30" "2018-10-03" "2018-10-05" "2018-10-04"

结合 mutate 动词使用

starwars %>% 
  mutate(性别 = case_when(
    sex == "male" ~ "雄性",
    sex == "female" ~ "雌性",
    sex == "hermaphroditic" ~ "雌雄同体",
    TRUE ~ "无"
    )) %>% 
  pull(性别) %>% 
  table()
#> .
#>     雌性 雌雄同体       无     雄性 
#>       16        1       10       60

pull()功能与 data$.类似,为了在管道中使用设计

2.3.3 计数函数

  • 计数

count()函数用来计数。下面两种表达方式等价。

df %>% count(a, b)
# same above
df %>% group_by(a, b) %>% summarise(n = n())
starwars %>% count(species)
#> # A tibble: 38 x 2
#>   species      n
#>   <chr>    <int>
#> 1 Aleena       1
#> 2 Besalisk     1
#> 3 Cerean       1
#> 4 Chagrian     1
#> 5 Clawdite     1
#> 6 Droid        6
#> # ... with 32 more rows
# same above 等价
starwars %>% group_by(species) %>% summarise(n = n())
#> # A tibble: 38 x 2
#>   species      n
#>   <chr>    <int>
#> 1 Aleena       1
#> 2 Besalisk     1
#> 3 Cerean       1
#> 4 Chagrian     1
#> 5 Clawdite     1
#> 6 Droid        6
#> # ... with 32 more rows
  • 非重复计数

n_distinct()length(unique(x))等价,但是更快更简洁。当我们需要给门店或订单之类数据去重计算时采用该函数。

x <- sample(1:10, 1e5, rep = TRUE)
length(unique(x))
#> [1] 10
n_distinct(x)
#> [1] 10

2.3.4 排序函数

dplyr共六种排序函数,模仿SQL2003中的排名函数。

  • row_number():等于 rank(ties.method = “first”)
  • min_rank(): 等于 rank(ties.method = “min”)
  • dense_rank(): 与min_rank()相似,但是没有间隔
  • percent_rank():返回0,1之间,通过min_rank()返回值缩放至[0,1]
x <- c(5, 1, 3, 2, 2, NA)
row_number(x)
#> [1]  5  1  4  2  3 NA
min_rank(x)
#> [1]  5  1  4  2  2 NA
dense_rank(x)
#> [1]  4  1  3  2  2 NA
percent_rank(x)
#> [1] 1.00 0.00 0.75 0.25 0.25   NA
cume_dist(x)
#> [1] 1.0 0.2 0.8 0.6 0.6  NA

2.3.5 提取向量

该系列函数是对[[的包装,方便提取向量。

nth(x, n, order_by = NULL, default = default_missing(x))
first(x, order_by = NULL, default = default_missing(x))
last(x, order_by = NULL, default = default_missing(x))
x <- 1:10
y <- 10:1
first(x)
#> [1] 1
last(y)
#> [1] 1
nth(x, 1)
#> [1] 1
nth(x, 5)
#> [1] 5

2.3.6 slice 系列

slice()函数让我们按照行数切片,让我们筛选,删除、重复某些行。和 python 中的 pandas 库的切片类似。 slice()共有如下几组函数:

  • slice_head() 和 slice_tail(),选着头和尾行 。

  • slice_sample() 随机选择行。

  • slice_min() 和 slice_max() 按照变量的最低值和最高值选择行。

如果用于 slice() 系列函数的数据集.data 是被 group_by() 过,那每个函数将作用在每一组上。例如,按照商品大类取每个商品大类前五的商品。

dt %>% 
  group_by(商品大类) %>% 
  slice_head(n = 5)

2.3.6.1 函数用法

slice(.data, ..., .preserve = FALSE)

slice_head(.data, ..., n, prop)

slice_tail(.data, ..., n, prop)

slice_min(.data, order_by, ..., n, prop, with_ties = TRUE)

slice_max(.data, order_by, ..., n, prop, with_ties = TRUE)

slice_sample(.data, ..., n, prop, weight_by = NULL, replace = FALSE)

2.3.6.2 参数解释

.data: 一个 data.frame , data frame extension (tibble)

…: 必须是整数,如果是正数将保留,负值将删除。提供的值超过行数的将会被忽略

.preserve :默认为FALSE,根据结果数据重新计算分组结构,否则保持原样分组

n,p: 提供要选择的行数 n,或行的比列比如 prop = 0.4,如果都未提供则默认n = 1

order_by: 要排序的变量或者是被函数作用的变量

with_ties: 针对 _min 或 _max 函数,相等时候是否强制输出指定行数。

weight_by: 抽样的权重

replace: 是否允许重复抽样,默认为FALSE

2.3.6.3 slice 案例

  • slice()
# 筛选第一行
mtcars %>% slice(1L)
#> # A tibble: 1 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1    21     6   160   110   3.9  2.62  16.5     0     1     4     4

# 筛选最后一行
mtcars %>% slice(n())
#> # A tibble: 1 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  21.4     4   121   109  4.11  2.78  18.6     1     1     4     2

# 筛选5至最后一行
mtcars %>% slice(5:n())
#> # A tibble: 28 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#> 2  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#> 3  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#> 4  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#> 5  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 6  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # ... with 22 more rows

# 删除前面四行
slice(mtcars, -(1:4))
#> # A tibble: 28 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#> 2  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#> 3  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#> 4  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#> 5  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 6  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # ... with 22 more rows
  • slice_head slice_tail
# 基于现有顺序筛选前面行或最后行
mtcars %>% slice_head(n = 5)
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 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
mtcars %>% slice_tail(n = 5)
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
#> 2  15.8     8 351     264  4.22  3.17  14.5     0     1     5     4
#> 3  19.7     6 145     175  3.62  2.77  15.5     0     1     5     6
#> 4  15       8 301     335  3.54  3.57  14.6     0     1     5     8
#> 5  21.4     4 121     109  4.11  2.78  18.6     1     1     4     2
  • slice_min slice_max
# 基于变量筛选
mtcars %>% slice_min(mpg, n = 5) #最小的五行
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  10.4     8   472   205  2.93  5.25  18.0     0     0     3     4
#> 2  10.4     8   460   215  3     5.42  17.8     0     0     3     4
#> 3  13.3     8   350   245  3.73  3.84  15.4     0     0     3     4
#> 4  14.3     8   360   245  3.21  3.57  15.8     0     0     3     4
#> 5  14.7     8   440   230  3.23  5.34  17.4     0     0     3     4
mtcars %>% slice_max(mpg, n = 5) #最大的五行
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  33.9     4  71.1    65  4.22  1.84  19.9     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  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
#> 5  27.3     4  79      66  4.08  1.94  18.9     1     1     4     1

# slice_min()可能返回更多行,通过with_ties参数控制
mtcars %>% slice_min(cyl, n = 1)
#> # A tibble: 11 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  22.8     4 108      93  3.85  2.32  18.6     1     1     4     1
#> 2  24.4     4 147.     62  3.69  3.19  20       1     0     4     2
#> 3  22.8     4 141.     95  3.92  3.15  22.9     1     0     4     2
#> 4  32.4     4  78.7    66  4.08  2.2   19.5     1     1     4     1
#> 5  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
#> 6  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
#> # ... with 5 more rows
mtcars %>% slice_min(cyl, n = 1, with_ties = FALSE)
#> # A tibble: 1 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
  • slice_sample

在数据集中抽样,通过 replace 参数控制是否可以重复。

mtcars %>% slice_sample(n = 5)
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  19.2     6 168.    123  3.92  3.44  18.3     1     0     4     4
#> 2  10.4     8 472     205  2.93  5.25  18.0     0     0     3     4
#> 3  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
#> 4  27.3     4  79      66  4.08  1.94  18.9     1     1     4     1
#> 5  13.3     8 350     245  3.73  3.84  15.4     0     0     3     4
mtcars %>% slice_sample(n = 5, replace = TRUE)
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  21.5     4  120.    97  3.7   2.46  20.0     1     0     3     1
#> 2  14.7     8  440    230  3.23  5.34  17.4     0     0     3     4
#> 3  14.7     8  440    230  3.23  5.34  17.4     0     0     3     4
#> 4  17.3     8  276.   180  3.07  3.73  17.6     0     0     3     3
#> 5  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1

weight_by 参数调整抽样权重

# 重量大的会更容易抽到
mtcars %>% slice_sample(weight_by = wt, n = 5)
#> # A tibble: 5 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  21.4     4   121   109  4.11  2.78  18.6     1     1     4     2
#> 2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
#> 3  15.5     8   318   150  2.76  3.52  16.9     0     0     3     2
#> 4  21       6   160   110  3.9   2.62  16.5     0     1     4     4
#> 5  10.4     8   472   205  2.93  5.25  18.0     0     0     3     4
  • 分组操作
df <- tibble(
  group = rep(c("a", "b", "c"), c(1, 2, 4)),
  x = runif(7)
)
df %>% group_by(group) %>% slice_head(n = 2)
#> # A tibble: 5 x 2
#> # Groups:   group [3]
#>   group     x
#>   <chr> <dbl>
#> 1 a     0.810
#> 2 b     0.802
#> 3 b     0.860
#> 4 c     0.344
#> 5 c     0.683

# 注意体会使用prop参数时的差异
df %>% group_by(group) %>% slice_head(prop = 0.4)  #仅c组返回一个,因为c组3个数字的 40%的前面还有数
#> # A tibble: 1 x 2
#> # Groups:   group [1]
#>   group     x
#>   <chr> <dbl>
#> 1 c     0.344
df %>% group_by(group) %>% slice_head(prop = 0.5) # 因为a组只有一个数字,前50%位没有数字
#> # A tibble: 3 x 2
#> # Groups:   group [2]
#>   group     x
#>   <chr> <dbl>
#> 1 b     0.802
#> 2 c     0.344
#> 3 c     0.683

2.3.7 group 系列

group 系列函数包含 group_by(),group_map(), group_nest(), group_split(), group_trim()等。 其中我常用group_by(),group_split()两个函数。group_by()是我们熟悉的动词,大部分数据操作中的分组操作由它完成。

  • group_by()
#group_by()不会改变数据框
by_cyl <- mtcars %>% group_by(cyl)
by_cyl
#> # A tibble: 32 x 11
#> # Groups:   cyl [3]
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 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
#> # ... with 26 more rows
# It changes how it acts with the other dplyr verbs:
by_cyl %>% summarise(
  disp = mean(disp),
  hp = mean(hp)
)
#> # A tibble: 3 x 3
#>     cyl  disp    hp
#>   <int> <dbl> <dbl>
#> 1     4  105.  82.6
#> 2     6  183. 122. 
#> 3     8  353. 209.
# group_by中可以添加计算字段 即mutate操作
mtcars %>% group_by(vsam = vs + am) %>%
  group_vars()
#> [1] "vsam"

- group_split()

目前该函数是实验性的,group_split() 功能与 base::split()相似,按照数据集的分组变量切割数据集。如下,将 iris 数据集按照 Species 分组并切割成长度为3的列表,每个子元素是 Species 变量的子数据集。Species 变量包含setosaversicolorvirginica三种情况。

ir <- iris %>%
  group_by(Species)

group_split(ir)
#> <list_of<
#>   tbl_df<
#>     Sepal.Length: double
#>     Sepal.Width : double
#>     Petal.Length: double
#>     Petal.Width : double
#>     Species     : factor<fb977>
#>   >
#> >[3]>
#> [[1]]
#> # A tibble: 50 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#>          <dbl>       <dbl>        <dbl>       <dbl> <fct>  
#> 1          5.1         3.5          1.4         0.2 setosa 
#> 2          4.9         3            1.4         0.2 setosa 
#> 3          4.7         3.2          1.3         0.2 setosa 
#> 4          4.6         3.1          1.5         0.2 setosa 
#> 5          5           3.6          1.4         0.2 setosa 
#> 6          5.4         3.9          1.7         0.4 setosa 
#> # ... with 44 more rows
#> 
#> [[2]]
#> # A tibble: 50 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
#>          <dbl>       <dbl>        <dbl>       <dbl> <fct>     
#> 1          7           3.2          4.7         1.4 versicolor
#> 2          6.4         3.2          4.5         1.5 versicolor
#> 3          6.9         3.1          4.9         1.5 versicolor
#> 4          5.5         2.3          4           1.3 versicolor
#> 5          6.5         2.8          4.6         1.5 versicolor
#> 6          5.7         2.8          4.5         1.3 versicolor
#> # ... with 44 more rows
#> 
#> [[3]]
#> # A tibble: 50 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species  
#>          <dbl>       <dbl>        <dbl>       <dbl> <fct>    
#> 1          6.3         3.3          6           2.5 virginica
#> 2          5.8         2.7          5.1         1.9 virginica
#> 3          7.1         3            5.9         2.1 virginica
#> 4          6.3         2.9          5.6         1.8 virginica
#> 5          6.5         3            5.8         2.2 virginica
#> 6          7.6         3            6.6         2.1 virginica
#> # ... with 44 more rows
group_keys(ir)
#> # A tibble: 3 x 1
#>   Species   
#>   <fct>     
#> 1 setosa    
#> 2 versicolor
#> 3 virginica
  • group_map()

group_map,group_modify,group_walk等三个函数是purrr类具有迭代风格的函数。简单关系数据的数据清洗一般不涉及,常用在建模等方面。

但是目前函数是实验性的,未来可能会发生变化。

# return a list
# 返回列表
mtcars %>%
  group_by(cyl) %>%
  group_map(~ head(.x, 2L))
#> [[1]]
#> # A tibble: 2 x 10
#>     mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  22.8  108     93  3.85  2.32  18.6     1     1     4     1
#> 2  24.4  147.    62  3.69  3.19  20       1     0     4     2
#> 
#> [[2]]
#> # A tibble: 2 x 10
#>     mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1    21   160   110   3.9  2.62  16.5     0     1     4     4
#> 2    21   160   110   3.9  2.88  17.0     0     1     4     4
#> 
#> [[3]]
#> # A tibble: 2 x 10
#>     mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#> 1  18.7   360   175  3.15  3.44  17.0     0     0     3     2
#> 2  14.3   360   245  3.21  3.57  15.8     0     0     3     4
iris %>%
  group_by(Species) %>%
  group_modify(~ {
    .x %>%
      purrr::map_dfc(fivenum) %>%
      mutate(nms = c("min", "Q1", "median", "Q3", "max"))
  })
#> # A tibble: 15 x 6
#> # Groups:   Species [3]
#>   Species    Sepal.Length Sepal.Width Petal.Length Petal.Width nms   
#>   <fct>             <dbl>       <dbl>        <dbl>       <dbl> <chr> 
#> 1 setosa              4.3         2.3          1           0.1 min   
#> 2 setosa              4.8         3.2          1.4         0.2 Q1    
#> 3 setosa              5           3.4          1.5         0.2 median
#> 4 setosa              5.2         3.7          1.6         0.3 Q3    
#> 5 setosa              5.8         4.4          1.9         0.6 max   
#> 6 versicolor          4.9         2            3           1   min   
#> # ... with 9 more rows

分组后批量输出

# group_walk
dir.create(temp <- tempfile())
iris %>%
  group_by(Species) %>%
  group_walk(~ write.csv(.x, file = file.path(temp, paste0(.y$Species, ".csv"))))
list.files(temp, pattern = "csv$")
unlink(temp, recursive = TRUE)
  • group_cols()

选择分组变量

gdf <- iris %>% group_by(Species)
gdf %>% select(group_cols())
#> # A tibble: 150 x 1
#> # Groups:   Species [3]
#>   Species
#>   <fct>  
#> 1 setosa 
#> 2 setosa 
#> 3 setosa 
#> 4 setosa 
#> 5 setosa 
#> 6 setosa 
#> # ... with 144 more rows

2.3.8 其它函数

有针对性学习函数可以有效提高学习效率,先浏览一遍 dplyr 中函数,再挑选觉得对自己有用的函数学习即可。

  • between
between(1:12, 7, 9)
#>  [1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE
  • pull
mtcars %>% pull(-1)
#>  [1] 4 4 1 1 2 1 4 2 2 4 4 3 3 3 4 4 4 1 2 1 1 2 2 4 2 1 2 2 4 6 8 2
mtcars %>% pull(cyl)
#>  [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
  • distinct
df <- tibble(
  x = sample(10, 100, rep = TRUE),
  y = sample(10, 100, rep = TRUE)
)

distinct(df, x)
distinct(df, x, .keep_all = TRUE)
distinct(df, diff = abs(x - y))
  • lead lag

在向量中查找“向前”或滞后的值,在比较当前值以及前后值时比较有用。

lag(x, n = 1L, default = NA, order_by = NULL, ...)

lead(x, n = 1L, default = NA, order_by = NULL, ...)
lag(1:5)
#> [1] NA  1  2  3  4
lead(1:5)
#> [1]  2  3  4  5 NA

lag(1:5, n = 1)
#> [1] NA  1  2  3  4
lag(1:5, n = 2)
#> [1] NA NA  1  2  3

order_by 参数控制顺序。

# If data are not already ordered, use `order_by`
scrambled <- slice_sample(tibble(year = 2000:2005, value = (0:5) ^ 2), prop = 1)

wrong <- mutate(scrambled, previous_year_value = lag(value))
arrange(wrong, year)
#> # A tibble: 6 x 3
#>    year value previous_year_value
#>   <int> <dbl>               <dbl>
#> 1  2000     0                   1
#> 2  2001     1                  25
#> 3  2002     4                  NA
#> 4  2003     9                   4
#> 5  2004    16                   0
#> 6  2005    25                   9

right <- mutate(scrambled, previous_year_value = lag(value, order_by = year))
arrange(right, year)
#> # A tibble: 6 x 3
#>    year value previous_year_value
#>   <int> <dbl>               <dbl>
#> 1  2000     0                  NA
#> 2  2001     1                   0
#> 3  2002     4                   1
#> 4  2003     9                   4
#> 5  2004    16                   9
#> 6  2005    25                  16

该函数在我们计算下单间隔天数时比较简洁方便

如需了解更多,可以通过学习slider包知道更多“滑动窗口函数”。

  • cummean cumsum cumall cumany

累计系列函数

x <- c(1, 3, 5, 2, 2)
cummean(x)
#> [1] 1.00 2.00 3.00 2.75 2.60
cumsum(x) / seq_along(x)
#> [1] 1.00 2.00 3.00 2.75 2.60

cumall(x < 5)
#> [1]  TRUE  TRUE FALSE FALSE FALSE
cumany(x == 3)
#> [1] FALSE  TRUE  TRUE  TRUE  TRUE
  • coalesce

用一组向量值替换NAS,该函数受 SQL 的 COALESCE 函数启发。

x <- sample(c(1:5, NA, NA, NA))
coalesce(x, 0L)
#> [1] 3 2 0 5 4 0 1 0
y <- c(1, 2, NA, NA, 5)
z <- c(NA, NA, 3, 4, 5)
coalesce(y, z)
#> [1] 1 2 3 4 5

在数据框中替换NA

df <- tibble( a= sample(c(1:3,NA,NA),10,replace = TRUE))
df %>% 
  mutate(a = coalesce(a,0))
#> # A tibble: 10 x 1
#>       a
#>   <dbl>
#> 1     1
#> 2     0
#> 3     3
#> 4     2
#> 5     2
#> 6     0
#> # ... with 4 more rows