tidyr :: в комплекте с вектором имен столбцов переменной длины - PullRequest
2 голосов
/ 02 марта 2020

Я могу использовать tidyr::complete для отображения пропущенных строк.

Например, с помощью следующего data.frame я могу легко представить пропущенный третий квартал:

suppressPackageStartupMessages({
  library(dplyr)
  library(tidyr)
})

set.seed(42)

df <- data.frame(
  id = c(rep(1, 3), rep(2, 3)),
  year = rep(2020, 3),
  quarter = c(1, 2, 4),
  data = runif(3)
)

df %>% complete(nesting(id, year), quarter = 1:4)
#> # A tibble: 8 x 4
#>      id  year quarter   data
#>   <dbl> <dbl>   <dbl>  <dbl>
#> 1     1  2020       1  0.915
#> 2     1  2020       2  0.937
#> 3     1  2020       3 NA    
#> 4     1  2020       4  0.286
#> 5     2  2020       1  0.915
#> 6     2  2020       2  0.937
#> 7     2  2020       3 NA    
#> 8     2  2020       4  0.286

Создано в 2020-03-02 пакетом Представления (v0.3.0)

Теперь я хочу создать оболочку для этого конкретного c варианта использования: он принимает в data.frame как минимум эти четыре столбца и выставляет пропущенные четверти.

Это достаточно просто, просто оберните вызов complete в функцию:

expose <- function(df) {
  complete(df, nesting(id, year), quarter = 1:4)
}

expose(df)
#> # A tibble: 8 x 4
#>      id  year quarter   data
#>   <dbl> <dbl>   <dbl>  <dbl>
#> 1     1  2020       1  0.915
#> 2     1  2020       2  0.937
#> 3     1  2020       3 NA    
#> 4     1  2020       4  0.286
#> 5     2  2020       1  0.915
#> 6     2  2020       2  0.937
#> 7     2  2020       3 NA    
#> 8     2  2020       4  0.286

Однако входящий data.frame может иметь другие столбцы, которые, как известно, являются постоянными для данного id. В этом случае функция не работает, так как она естественным образом устанавливает для этих столбцов значение NA в пропущенных строках.

df <- data.frame(
  id = c(rep(1, 3), rep(2, 3)),
  name = c(rep("A", 3), rep("B", 3)),
  country = c(rep("AU", 3), rep("BR", 3)),
  year = rep(2020, 3),
  quarter = c(1, 2, 4),
  data = runif(3)
)

expose(df)
#> # A tibble: 8 x 6
#>      id  year quarter name  country   data
#>   <dbl> <dbl>   <dbl> <fct> <fct>    <dbl>
#> 1     1  2020       1 A     AU       0.830
#> 2     1  2020       2 A     AU       0.642
#> 3     1  2020       3 <NA>  <NA>    NA    
#> 4     1  2020       4 A     AU       0.519
#> 5     2  2020       1 B     BR       0.830
#> 6     2  2020       2 B     BR       0.642
#> 7     2  2020       3 <NA>  <NA>    NA    
#> 8     2  2020       4 B     BR       0.519

Чтобы избежать этого, мне нужно добавить эти столбцы в nesting call.

Если бы это был только один столбец, я мог бы добавить в функцию аргумент для имени столбца, который я бы затем использовал с nesting(..., .data[[colname]]). Однако местоимение .data не работает с векторами (.data[c("name1", "name2")] не работает).

Итак, как я могу добавить несколько переменных столбцов к вызову nesting?

Ответы [ 2 ]

2 голосов
/ 02 марта 2020

Если вы посмотрите на tidyr::nesting, вы увидите, что он опирается на tidyr:::dots_cols, который опирается на rlang для интерпретации имен столбцов (в частности, rlang::enquos).

Лучший способ поэтому для взаимодействия с tidyr::nesting необходимо использовать конструкцию rlang.

library(dplyr)
library(tidyr)

expose <- function(df, ...) {
  dots <- rlang::exprs(id, year, ...)
  complete(df, nesting(!!! dots), quarter = 1:4)
}

df <- data.frame(
  id = c(rep(1, 3), rep(2, 3)),
  name = c(rep("A", 3), rep("B", 3)),
  country = c(rep("AU", 3), rep("BR", 3)),
  year = rep(2020, 3),
  quarter = c(1, 2, 4),
  data = runif(3)
)

expose(df)
#> # A tibble: 8 x 6
#>      id  year quarter name  country    data
#>   <dbl> <dbl>   <dbl> <fct> <fct>     <dbl>
#> 1     1  2020       1 A     AU       0.0417
#> 2     1  2020       2 A     AU       0.365 
#> 3     1  2020       3 <NA>  <NA>    NA     
#> 4     1  2020       4 A     AU       0.690 
#> 5     2  2020       1 B     BR       0.0417
#> 6     2  2020       2 B     BR       0.365 
#> 7     2  2020       3 <NA>  <NA>    NA     
#> 8     2  2020       4 B     BR       0.690
expose(df, name)
#> # A tibble: 8 x 6
#>      id  year name  quarter country    data
#>   <dbl> <dbl> <fct>   <dbl> <fct>     <dbl>
#> 1     1  2020 A           1 AU       0.0417
#> 2     1  2020 A           2 AU       0.365 
#> 3     1  2020 A           3 <NA>    NA     
#> 4     1  2020 A           4 AU       0.690 
#> 5     2  2020 B           1 BR       0.0417
#> 6     2  2020 B           2 BR       0.365 
#> 7     2  2020 B           3 <NA>    NA     
#> 8     2  2020 B           4 BR       0.690
expose(df, name, country)
#> # A tibble: 8 x 6
#>      id  year name  country quarter    data
#>   <dbl> <dbl> <fct> <fct>     <dbl>   <dbl>
#> 1     1  2020 A     AU            1  0.0417
#> 2     1  2020 A     AU            2  0.365 
#> 3     1  2020 A     AU            3 NA     
#> 4     1  2020 A     AU            4  0.690 
#> 5     2  2020 B     BR            1  0.0417
#> 6     2  2020 B     BR            2  0.365 
#> 7     2  2020 B     BR            3 NA     
#> 8     2  2020 B     BR            4  0.690

Создано в 2020-03-02 пакетом Представить (v0.3.0)

0 голосов
/ 02 марта 2020

Библиотека rlang включает в себя очень мощный объект list2, который позволяет выполнять сращивание с помощью оператора "большого взрыва" (!!!). Это позволяет нам передавать nesting единственный объект, который интерпретируется принимающей функцией как последовательность аргументов.

Следовательно, мы можем добавить аргумент точек в функцию, которая получает все остальные столбцы для вложения с помощью преобразуйте имена в символы, а затем передайте их в nesting:

suppressPackageStartupMessages({
  library(dplyr)
  library(rlang)
  library(tidyr)
})

set.seed(42)

expose <- function(df, ...) {
  x <- list2(...)
  x <- lapply(x, sym)
  complete(df, nesting(id, year, !!!x), quarter = 1:4)
}

df <- data.frame(
  id = c(rep(1, 3), rep(2, 3)),
  name = c(rep("A", 3), rep("B", 3)),
  country = c(rep("AU", 3), rep("BR", 3)),
  year = rep(2020, 3),
  quarter = c(1, 2, 4),
  data = runif(3)
)

expose(df, "name", "country")
#> # A tibble: 8 x 6
#>      id  year name  country quarter   data
#>   <dbl> <dbl> <fct> <fct>     <dbl>  <dbl>
#> 1     1  2020 A     AU            1  0.915
#> 2     1  2020 A     AU            2  0.937
#> 3     1  2020 A     AU            3 NA    
#> 4     1  2020 A     AU            4  0.286
#> 5     2  2020 B     BR            1  0.915
#> 6     2  2020 B     BR            2  0.937
#> 7     2  2020 B     BR            3 NA    
#> 8     2  2020 B     BR            4  0.286

Создано в 2020-03-02 пакетом prex (v0.3.0)

...