将列表中的表达式捕获为文本
Capturing expressions inside lists as text
我目前有这个函数,它接受一个 table 和两个表达式列表,并对它们求值,将它们变成两个矩阵。我使用两个列表而不是 ...
,因为我需要能够确定表达式是属于 Y 还是 Z。
func = function(tb, Y, Z) {
Y_matrix = enquo(Y) %>%
eval_tidy(tb) %>%
as.data.frame %>%
as.matrix
Z_matrix = enquo(Z) %>%
eval_tidy(tb) %>%
as.data.frame %>%
as.matrix
list(Y_matrix, Z_matrix)
}
例如:
> tb = data.frame(a = 1:3, b = 3:1, c = 2*(1:3))
> func(tb, list(a + b, a - b), list(a*c, a + b + c))
[[1]]
c.4L..4L..4L. c..2L..0L..2L.
[1,] 4 -2
[2,] 4 0
[3,] 4 2
[[2]]
c.2..8..18. c.6..8..10.
[1,] 2 6
[2,] 8 8
[3,] 18 10
但是,我还想将列表中的表达式捕获为文本,这样我就可以使用它们来命名列。例如,我想要的输出是这样的:
> func(tb, list(a + b, a - b), list(a*c, a + b + c))
[[1]]
a+b a-b
[1,] 4 -2
[2,] 4 0
[3,] 4 2
[[2]]
a*c a + b + c
[1,] 2 6
[2,] 8 8
[3,] 18 10
我该怎么做?
我们可以将参数作为一个 quosure 传递,然后进行评估 (!!!
)
library(tidyverse)
f1 <- function(tb, Y, Z) {
Y_matrix <- tb %>%
transmute(!!! Y)
Z_matrix <- tb %>%
transmute(!!! Z)
list(Y_matrix, Z_matrix)
}
f1(tb, quos(a + b, a - b), quos(a*c, a + b + c))
#[[1]]
# a + b a - b
#1 4 -2
#2 4 0
#3 4 2
#[[2]]
# a * c a + b + c
#1 2 6
#2 8 8
#3 18 10
您可以使用 deparse
之类的方法遍历列表中的语言元素,将其转换为字符串。例如
func = function(tb, Y, Z) {
Y_names <- map_chr(as.list(enexpr(Y))[-1], deparse)
Y_matrix = enquo(Y) %>%
eval_tidy(tb) %>%
as.data.frame %>%
set_names(Y_names) %>%
as.matrix
Z_names <- map_chr(as.list(enexpr(Z))[-1], deparse)
Z_matrix = enquo(Z) %>%
eval_tidy(tb) %>%
as.data.frame %>%
set_names(Z_names) %>%
as.matrix
list(Y_matrix, Z_matrix)
}
适用于此示例
func(tb, list(a + b, a - b), list(a*c, a + b + c))
# [[1]]
# a + b a - b
# [1,] 4 -2
# [2,] 4 0
# [3,] 4 2
# [[2]]
# a * c a + b + c
# [1,] 2 6
# [2,] 8 8
# [3,] 18 10
我目前有这个函数,它接受一个 table 和两个表达式列表,并对它们求值,将它们变成两个矩阵。我使用两个列表而不是 ...
,因为我需要能够确定表达式是属于 Y 还是 Z。
func = function(tb, Y, Z) {
Y_matrix = enquo(Y) %>%
eval_tidy(tb) %>%
as.data.frame %>%
as.matrix
Z_matrix = enquo(Z) %>%
eval_tidy(tb) %>%
as.data.frame %>%
as.matrix
list(Y_matrix, Z_matrix)
}
例如:
> tb = data.frame(a = 1:3, b = 3:1, c = 2*(1:3))
> func(tb, list(a + b, a - b), list(a*c, a + b + c))
[[1]]
c.4L..4L..4L. c..2L..0L..2L.
[1,] 4 -2
[2,] 4 0
[3,] 4 2
[[2]]
c.2..8..18. c.6..8..10.
[1,] 2 6
[2,] 8 8
[3,] 18 10
但是,我还想将列表中的表达式捕获为文本,这样我就可以使用它们来命名列。例如,我想要的输出是这样的:
> func(tb, list(a + b, a - b), list(a*c, a + b + c))
[[1]]
a+b a-b
[1,] 4 -2
[2,] 4 0
[3,] 4 2
[[2]]
a*c a + b + c
[1,] 2 6
[2,] 8 8
[3,] 18 10
我该怎么做?
我们可以将参数作为一个 quosure 传递,然后进行评估 (!!!
)
library(tidyverse)
f1 <- function(tb, Y, Z) {
Y_matrix <- tb %>%
transmute(!!! Y)
Z_matrix <- tb %>%
transmute(!!! Z)
list(Y_matrix, Z_matrix)
}
f1(tb, quos(a + b, a - b), quos(a*c, a + b + c))
#[[1]]
# a + b a - b
#1 4 -2
#2 4 0
#3 4 2
#[[2]]
# a * c a + b + c
#1 2 6
#2 8 8
#3 18 10
您可以使用 deparse
之类的方法遍历列表中的语言元素,将其转换为字符串。例如
func = function(tb, Y, Z) {
Y_names <- map_chr(as.list(enexpr(Y))[-1], deparse)
Y_matrix = enquo(Y) %>%
eval_tidy(tb) %>%
as.data.frame %>%
set_names(Y_names) %>%
as.matrix
Z_names <- map_chr(as.list(enexpr(Z))[-1], deparse)
Z_matrix = enquo(Z) %>%
eval_tidy(tb) %>%
as.data.frame %>%
set_names(Z_names) %>%
as.matrix
list(Y_matrix, Z_matrix)
}
适用于此示例
func(tb, list(a + b, a - b), list(a*c, a + b + c))
# [[1]]
# a + b a - b
# [1,] 4 -2
# [2,] 4 0
# [3,] 4 2
# [[2]]
# a * c a + b + c
# [1,] 2 6
# [2,] 8 8
# [3,] 18 10