簡體   English   中英

dplyr::across 和 purrr::modify_if/at 之間有什么區別嗎?

[英]Any difference between dplyr::across and purrr::modify_if/at?

如果想將一個函數應用於一個或多個列,可選地基於某些標准,似乎有兩種相同的方法可以使用 Tidyverse 包來做到這一點。 我想知道是否有任何理由更喜歡其中一個?

例如,如果想要將所有數字列轉換為字符,您可以執行以下任一操作:

library(dplyr, warn.conflicts = FALSE)
library(purrr)
library(ggplot2)

mpg |> 
  mutate(across(where(is.numeric), as.character)) |> 
  slice_head(n = 5)
#> # A tibble: 5 × 11
#>   manufacturer model displ year  cyl   trans      drv   cty   hwy   fl    class 
#>   <chr>        <chr> <chr> <chr> <chr> <chr>      <chr> <chr> <chr> <chr> <chr> 
#> 1 audi         a4    1.8   1999  4     auto(l5)   f     18    29    p     compa…
#> 2 audi         a4    1.8   1999  4     manual(m5) f     21    29    p     compa…
#> 3 audi         a4    2     2008  4     manual(m6) f     20    31    p     compa…
#> 4 audi         a4    2     2008  4     auto(av)   f     21    30    p     compa…
#> 5 audi         a4    2.8   1999  6     auto(l5)   f     16    26    p     compa…

mpg |> 
  modify_if(is.numeric, as.character) |> 
  slice_head(n = 5)
#> # A tibble: 5 × 11
#>   manufacturer model displ year  cyl   trans      drv   cty   hwy   fl    class 
#>   <chr>        <chr> <chr> <chr> <chr> <chr>      <chr> <chr> <chr> <chr> <chr> 
#> 1 audi         a4    1.8   1999  4     auto(l5)   f     18    29    p     compa…
#> 2 audi         a4    1.8   1999  4     manual(m5) f     21    29    p     compa…
#> 3 audi         a4    2     2008  4     manual(m6) f     20    31    p     compa…
#> 4 audi         a4    2     2008  4     auto(av)   f     21    30    p     compa…
#> 5 audi         a4    2.8   1999  6     auto(l5)   f     16    26    p     compa…

或者,如果您只想更改年份列,則以下任一方法都可以:

library(dplyr, warn.conflicts = FALSE)
library(purrr)
library(ggplot2)

mpg |> 
  mutate(year = as.character(year)) |> 
  slice_head(n = 5)
#> # A tibble: 5 × 11
#>   manufacturer model displ year    cyl trans      drv     cty   hwy fl    class 
#>   <chr>        <chr> <dbl> <chr> <int> <chr>      <chr> <int> <int> <chr> <chr> 
#> 1 audi         a4      1.8 1999      4 auto(l5)   f        18    29 p     compa…
#> 2 audi         a4      1.8 1999      4 manual(m5) f        21    29 p     compa…
#> 3 audi         a4      2   2008      4 manual(m6) f        20    31 p     compa…
#> 4 audi         a4      2   2008      4 auto(av)   f        21    30 p     compa…
#> 5 audi         a4      2.8 1999      6 auto(l5)   f        16    26 p     compa…

mpg |> 
  modify_at('year', as.character) |> 
  slice_head(n = 5)
#> # A tibble: 5 × 11
#>   manufacturer model displ year    cyl trans      drv     cty   hwy fl    class 
#>   <chr>        <chr> <dbl> <chr> <int> <chr>      <chr> <int> <int> <chr> <chr> 
#> 1 audi         a4      1.8 1999      4 auto(l5)   f        18    29 p     compa…
#> 2 audi         a4      1.8 1999      4 manual(m5) f        21    29 p     compa…
#> 3 audi         a4      2   2008      4 manual(m6) f        20    31 p     compa…
#> 4 audi         a4      2   2008      4 auto(av)   f        21    30 p     compa…
#> 5 audi         a4      2.8 1999      6 auto(l5)   f        16    26 p     compa…

除了可能不必額外導入 purrr 之外,是否有任何理由更喜歡其中一個? 還是這些相同?

我不確定這是唯一的區別,但mutate只能在data.frame上運行,而modify_if也可以在list上運行。

library(dplyr)
library(purrr)

list(a=1, b="b") %>% modify_if(is.numeric, `+`, 1)
# $a
# [1] 2
# $b
# [1] "b"

list(a=1, b="b") %>% mutate(across(where(is.numeric), ~ . + 1))
# Error in UseMethod("mutate") : 
#   no applicable method for 'mutate' applied to an object of class "list"

雖然您已經證明,給定繼承data.frame的輸入,兩者都應該產生相同的輸出。

identical(
  iris %>% modify_if(is.numeric, `+`, 1),
  iris %>% mutate(across(where(is.numeric), ~ . + 1))
)
# [1] TRUE

不過有趣的是, modify_if的速度快得多:

bench::mark(
  purrr = iris %>% modify_if(is.numeric, `+`, 1),
  dplyr = iris %>% mutate(across(where(is.numeric), ~ . + 1))
)
# # A tibble: 2 x 13
#   expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result         memory              time   gc    
#   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list>         <list>              <list> <list>
# 1 purrr         220us  254.5us     3816.    4.88KB     2.65  1440     1      377ms <df [150 x 5]> <Rprofmem [4 x 3]>  <benc~ <tibb~
# 2 dplyr        1.58ms   1.91ms      515.   11.34KB     2.50   206     1      400ms <df [150 x 5]> <Rprofmem [19 x 3]> <benc~ <tibb~

bench::mark 自動繪圖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM