dplyr::mutate 是否适用于记录样式的列?
Does dplyr::mutate work with record-style columns?
我最近一直在测试 vctrs 包,尤其是他们最近称为 "record-style" 对象的东西,我想知道是否有任何方法可以让他们与 dplyr::mutate 一起玩得很好。目前,当 dplyr::mutate 每当我尝试使用它们时,都会给我一个关于对象长度的错误。
我不知道合适的内置类型,因此作为代表,我将使用 this vignette.
中描述的有理 class
library("vctrs")
library("dplyr")
new_rational <- function(n = integer(), d = integer()) {
vec_assert(n, ptype = integer())
vec_assert(d, ptype = integer())
new_rcrd(list(n = n, d = d), class = "vctrs_rational")
}
format.vctrs_rational <- function(x, ...) {
n <- field(x, "n")
d <- field(x, "d")
out <- paste0(n, "/", d)
out[is.na(n) | is.na(d)] <- NA
out
}
到目前为止一切顺利,但是当我尝试使用 dplyr::mutate 创建有理数列时,出现错误
df <- data.frame(n = c(1L, 2L, 3L), d = 2L)
df %>% dplyr::mutate(frac = new_rational(n, d))
#> Error: Column `frac` must be length 3 (the number of rows) or one, not 2
但是在 base R 中创建列工作得很好:
df$rational <- new_rational(df$n, df$d)
df
#> n d rational
#> 1 1 2 1/2
#> 2 2 2 2/2
#> 3 3 2 3/2
使用 dplyr::mutate 是否有一些技巧可以让它工作,或者这是不可能的?
new_rational
returns 列表格式的输出如下所示
> typeof(new_rational(n=1L, d=2L))
[1] "list"
因此,我们可以使用 map
或 as.list
“@Ronak 的建议”将输出作为列表,然后使用 unnest
。
df %>% dplyr::mutate(frac = purrr::map2(n,d, ~new_rational(.x, .y))) %>%
tidyr::unnest(cols=c(frac))
# A tibble: 3 x 3
n d frac
<int> <int> <vctrs_rt>
1 1 2 1/2
2 2 2 2/2
3 3 2 3/2
从 vctrs 0.3.6 / R 4.0.3 开始,您的 reprex 工作正常:
library("vctrs")
library("dplyr")
new_rational <- function(n = integer(), d = integer()) {
vec_assert(n, ptype = integer())
vec_assert(d, ptype = integer())
new_rcrd(list(n = n, d = d), class = "vctrs_rational")
}
format.vctrs_rational <- function(x, ...) {
n <- field(x, "n")
d <- field(x, "d")
out <- paste0(n, "/", d)
out[is.na(n) | is.na(d)] <- NA
out
}
df <- data.frame(n = c(1L, 2L, 3L), d = 2L)
df %>% dplyr::mutate(frac = new_rational(n, d))
#> n d frac
#> 1 1 2 1/2
#> 2 2 2 2/2
#> 3 3 2 3/2
由 reprex package (v0.3.0)
创建于 2021-02-03
我最近一直在测试 vctrs 包,尤其是他们最近称为 "record-style" 对象的东西,我想知道是否有任何方法可以让他们与 dplyr::mutate 一起玩得很好。目前,当 dplyr::mutate 每当我尝试使用它们时,都会给我一个关于对象长度的错误。
我不知道合适的内置类型,因此作为代表,我将使用 this vignette.
中描述的有理 classlibrary("vctrs")
library("dplyr")
new_rational <- function(n = integer(), d = integer()) {
vec_assert(n, ptype = integer())
vec_assert(d, ptype = integer())
new_rcrd(list(n = n, d = d), class = "vctrs_rational")
}
format.vctrs_rational <- function(x, ...) {
n <- field(x, "n")
d <- field(x, "d")
out <- paste0(n, "/", d)
out[is.na(n) | is.na(d)] <- NA
out
}
到目前为止一切顺利,但是当我尝试使用 dplyr::mutate 创建有理数列时,出现错误
df <- data.frame(n = c(1L, 2L, 3L), d = 2L)
df %>% dplyr::mutate(frac = new_rational(n, d))
#> Error: Column `frac` must be length 3 (the number of rows) or one, not 2
但是在 base R 中创建列工作得很好:
df$rational <- new_rational(df$n, df$d)
df
#> n d rational
#> 1 1 2 1/2
#> 2 2 2 2/2
#> 3 3 2 3/2
使用 dplyr::mutate 是否有一些技巧可以让它工作,或者这是不可能的?
new_rational
returns 列表格式的输出如下所示
> typeof(new_rational(n=1L, d=2L))
[1] "list"
因此,我们可以使用 map
或 as.list
“@Ronak 的建议”将输出作为列表,然后使用 unnest
。
df %>% dplyr::mutate(frac = purrr::map2(n,d, ~new_rational(.x, .y))) %>%
tidyr::unnest(cols=c(frac))
# A tibble: 3 x 3
n d frac
<int> <int> <vctrs_rt>
1 1 2 1/2
2 2 2 2/2
3 3 2 3/2
从 vctrs 0.3.6 / R 4.0.3 开始,您的 reprex 工作正常:
library("vctrs")
library("dplyr")
new_rational <- function(n = integer(), d = integer()) {
vec_assert(n, ptype = integer())
vec_assert(d, ptype = integer())
new_rcrd(list(n = n, d = d), class = "vctrs_rational")
}
format.vctrs_rational <- function(x, ...) {
n <- field(x, "n")
d <- field(x, "d")
out <- paste0(n, "/", d)
out[is.na(n) | is.na(d)] <- NA
out
}
df <- data.frame(n = c(1L, 2L, 3L), d = 2L)
df %>% dplyr::mutate(frac = new_rational(n, d))
#> n d frac
#> 1 1 2 1/2
#> 2 2 2 2/2
#> 3 3 2 3/2
由 reprex package (v0.3.0)
创建于 2021-02-03