在带有 dplyr (!!paste0, {{}}, as.name(), eval(parse(text=)
using a composite to call a variable dynmically in custom build function with dplyr (!!paste0, {{}}, as.name(), eval(parse(text=)
这是以下问题的扩展:, (2) and also asked in the comments to (2) by Mario Reutter。
library(dplyr, tidyverse)
string <- c("car", "train", 'bike', 'plain')
speed1 <- runif(4, min = 0, max = 10000)
speed2 <- runif(4, min = 0, max = 10000)
n1 <- sample(1:100, 4)
n1_plus <- sample(1:100, 4)
n1_minus <- sample(1:100, 4)
n2 <- sample(1:100, 4)
df <- data.frame(string, speed1, speed2, n1, n2, n1_plus, n1_minus)
感谢 akrun's 我可以构建以下函数:
my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}" := paste0(format({{V1}}, big.mark = ",") ,
'\n(' , format({{V2}}, big.mark = ",") , ')'))}
df<-df%>%my_fun(speed1, n1)
使用"{{V1}}_{{V2}}" :=
定义的复合名称创建新变量。
但是,我如何在等式右侧调用复合变量名称?例如。将 format({{V2}}, big.mark = ",")
替换为 format('{{V2}}_plus', big.mark = ",")
。我试过了(不工作):
my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}_plus" := paste0(format({{V1}}, big.mark = ",") ,
'\n(' , format('{{V2}}_plus', big.mark = ",") , ')'))}
df<-df%>%my_fun(speed1, n1)
期望的输出: 我希望有一个新列 speed1_n1_plus
结合了 speed1
和 n1_plus
的值:
string speed1 speed2 n1 n2 n1_plus n1_minus speed1_n1_plus
1 car 3958.415 1049.172 70 91 25 53 3,958.415\n(25)
2 train 6203.919 8639.160 52 92 14 91 6,203.919\n(14)
3 bike 2966.391 2997.303 35 55 46 61 2,966.391\n(46)
4 plain 2755.266 1627.379 98 66 8 49 2,755.266\n( 8)
我只需要对多个具有相似名称的变量进行操作。变量名称是 'core' 名称(在本例中为 'n1'、{{V2}}
)以及后缀和前缀的组合。我想避免为每个变量名添加额外的参数,因为它只为核心名称添加了一个后缀。
我在尝试:!!paste0, as.name(), eval(parse(text=), ...,这可能在函数外工作,但对我来说不在函数内。
my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}_plus" := paste0(format({{V1}}, big.mark = ","),
"\n(", format(!! rlang::sym(paste0(rlang::as_string(ensym(V2)), "_plus")), big.mark = ","), ")"))}
-测试
df %>%
my_fun(speed1, n1)
string speed1 speed2 n1 n2 n1_plus n1_minus speed1_n1_plus
1 car 4453.441 3336.7287 92 97 28 56 4,453.441\n(28)
2 train 7718.381 638.5120 82 61 9 13 7,718.381\n( 9)
3 bike 4648.093 4267.8390 7 92 83 29 4,648.093\n(83)
4 plain 3815.145 793.6886 18 56 30 46 3,815.145\n(30)
我同意在 mutate
中的赋值右侧使用变量名会有所帮助。之所以没有实施,是因为您可以通过以更长的格式适当地格式化 data_frame
来更有效地执行此操作。
对我来说,speed1
& n1
和 speed2
& n2
似乎是成对的。因此,您可以将 df 从包含 4 行(每辆车 类型 ,即汽车、火车等)转换为 8 行(每辆车 实例 ,即 car1、car2 等)。
在您的示例中,以这种更长的格式构建 data_frame
会更容易,但由于您可能必须使用指定格式的数据库,让我们重新格式化(注意:这非常乏味因为一些信息存储在变量 names 中,需要转换回单个单元格):
df_long = df %>% pivot_longer(-string) %>% #expand on everything but the column "string" (super long format but we need this to grab the information from the column names)
mutate(number = gsub("\D+", "", name), name = gsub("\d+", "", name)) #separate the numbers from the variable names
#separate speed and everything starting with "n" and get them into a wider format
df_n = df_long %>% filter(grepl("^n", name)) %>% pivot_wider(names_from=name)
df_rest = df_long %>% filter(grepl("^n", name)==F) %>% pivot_wider(names_from=name)
df_tidy = full_join(df_rest, df_n) #join the data frames together
View(df_tidy) #take a look how the df looks differently now (including explicit NAs since n2_plus and n2_minus don't exist in your example)
现在您可以简单地执行此操作以获得您想要的结果:
df_tidy = df_tidy %>% mutate(result = paste0(format(speed, big.mark=","), "\n(", format(n_plus, big.mark=","), ")"))
注意:选择更长的格式可能有意义,这样 n
、n_plus
和 n_minus
不是不同的列,而是在另一列中编码 n_kind
因子水平为“标准”、“加”和“减”。但我不能从你的例子中判断。
这是以下问题的扩展:
library(dplyr, tidyverse)
string <- c("car", "train", 'bike', 'plain')
speed1 <- runif(4, min = 0, max = 10000)
speed2 <- runif(4, min = 0, max = 10000)
n1 <- sample(1:100, 4)
n1_plus <- sample(1:100, 4)
n1_minus <- sample(1:100, 4)
n2 <- sample(1:100, 4)
df <- data.frame(string, speed1, speed2, n1, n2, n1_plus, n1_minus)
感谢 akrun's
my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}" := paste0(format({{V1}}, big.mark = ",") ,
'\n(' , format({{V2}}, big.mark = ",") , ')'))}
df<-df%>%my_fun(speed1, n1)
使用"{{V1}}_{{V2}}" :=
定义的复合名称创建新变量。
但是,我如何在等式右侧调用复合变量名称?例如。将 format({{V2}}, big.mark = ",")
替换为 format('{{V2}}_plus', big.mark = ",")
。我试过了(不工作):
my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}_plus" := paste0(format({{V1}}, big.mark = ",") ,
'\n(' , format('{{V2}}_plus', big.mark = ",") , ')'))}
df<-df%>%my_fun(speed1, n1)
期望的输出: 我希望有一个新列 speed1_n1_plus
结合了 speed1
和 n1_plus
的值:
string speed1 speed2 n1 n2 n1_plus n1_minus speed1_n1_plus
1 car 3958.415 1049.172 70 91 25 53 3,958.415\n(25)
2 train 6203.919 8639.160 52 92 14 91 6,203.919\n(14)
3 bike 2966.391 2997.303 35 55 46 61 2,966.391\n(46)
4 plain 2755.266 1627.379 98 66 8 49 2,755.266\n( 8)
我只需要对多个具有相似名称的变量进行操作。变量名称是 'core' 名称(在本例中为 'n1'、{{V2}}
)以及后缀和前缀的组合。我想避免为每个变量名添加额外的参数,因为它只为核心名称添加了一个后缀。
我在尝试:!!paste0, as.name(), eval(parse(text=), ...,这可能在函数外工作,但对我来说不在函数内。
my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}_plus" := paste0(format({{V1}}, big.mark = ","),
"\n(", format(!! rlang::sym(paste0(rlang::as_string(ensym(V2)), "_plus")), big.mark = ","), ")"))}
-测试
df %>%
my_fun(speed1, n1)
string speed1 speed2 n1 n2 n1_plus n1_minus speed1_n1_plus
1 car 4453.441 3336.7287 92 97 28 56 4,453.441\n(28)
2 train 7718.381 638.5120 82 61 9 13 7,718.381\n( 9)
3 bike 4648.093 4267.8390 7 92 83 29 4,648.093\n(83)
4 plain 3815.145 793.6886 18 56 30 46 3,815.145\n(30)
我同意在 mutate
中的赋值右侧使用变量名会有所帮助。之所以没有实施,是因为您可以通过以更长的格式适当地格式化 data_frame
来更有效地执行此操作。
对我来说,speed1
& n1
和 speed2
& n2
似乎是成对的。因此,您可以将 df 从包含 4 行(每辆车 类型 ,即汽车、火车等)转换为 8 行(每辆车 实例 ,即 car1、car2 等)。
在您的示例中,以这种更长的格式构建 data_frame
会更容易,但由于您可能必须使用指定格式的数据库,让我们重新格式化(注意:这非常乏味因为一些信息存储在变量 names 中,需要转换回单个单元格):
df_long = df %>% pivot_longer(-string) %>% #expand on everything but the column "string" (super long format but we need this to grab the information from the column names)
mutate(number = gsub("\D+", "", name), name = gsub("\d+", "", name)) #separate the numbers from the variable names
#separate speed and everything starting with "n" and get them into a wider format
df_n = df_long %>% filter(grepl("^n", name)) %>% pivot_wider(names_from=name)
df_rest = df_long %>% filter(grepl("^n", name)==F) %>% pivot_wider(names_from=name)
df_tidy = full_join(df_rest, df_n) #join the data frames together
View(df_tidy) #take a look how the df looks differently now (including explicit NAs since n2_plus and n2_minus don't exist in your example)
现在您可以简单地执行此操作以获得您想要的结果:
df_tidy = df_tidy %>% mutate(result = paste0(format(speed, big.mark=","), "\n(", format(n_plus, big.mark=","), ")"))
注意:选择更长的格式可能有意义,这样 n
、n_plus
和 n_minus
不是不同的列,而是在另一列中编码 n_kind
因子水平为“标准”、“加”和“减”。但我不能从你的例子中判断。