gpt4 book ai didi

r - 函数内 enquo() 和 toString() 之间的区别

转载 作者:行者123 更新时间:2023-12-02 19:08:32 27 4
gpt4 key购买 nike

我对 enquo 和 toString 的使用仍然有点困惑。在下面的示例中,我基本上只是尝试过滤数据框并在最后对行进行求和。我真的不明白为什么 enquo 和 toString 对我想做的第一件事做同样的事情(过滤器 --> 选项 1 和 2 给出相同的结果),但对我想做的第二件事却没有做同样的事情(总和 -->选项 1 有效,但选项 2 给我一个错误)。难道只是因为我在 dplyr 管道中使用它?

library(dplyr)
library(tidyverse)


### define dataframe
dataframe_test <- data.frame(
column_test = c(100,99,99,90,89,50),
month_test = c("2020-09-01", "2020-09-01","2020-09-01", "2020-09-01","2020-10-01","2020-10-01")
)



test_function <- function(df, df_col_indicator, df_col_month, char_month) {


### define variables for enquo, ensym, toString
df_col_indicator_enquo <- enquo(df_col_indicator)
df_col_indicator_ensym <- ensym(df_col_indicator)
df_col_indicator_toString <- toString(df_col_indicator)

df_col_month_ensym <- ensym(df_col_month)


dataframe2 <- df %>%
filter(!!df_col_month_ensym == char_month) %>% # filter for month
slice_max(!!df_col_indicator_ensym, n = 3) %>% # slice top 3 observations

## two options for filter
# option 1
filter(!!df_col_indicator_ensym == df[2, df_col_indicator_toString]) # filter for observations with same observation as second row
# option 2
#filter(!!df_col_indicator_ensym == df[2, !!df_col_indicator_enquo])


## two options for sum
# option 1
bb <- sum(dataframe2[ , df_col_indicator_toString]) # sum up observations

# option 2
#bb <- sum(dataframe2[ , !!df_col_indicator_enquo])

return(bb)

}


test_function(df = dataframe_test, df_col_indicator = "column_test", df_col_month = "month_test" , char_month = "2020-09-01")

编辑:

谢谢大家的回答。呵呵,好吧,我不得不承认这个例子有点愚蠢,但我在这里尽量保持简单。我最初的问题实际上是这个(见下文)。我基本上尝试选择一列中的前 5 个数字。存在三种不同的结果。 1)如果超过5个==100,那么我想随机将5个观察结果存储在列表(指示器)中,将其他观察结果存储在列表(星号)中。 2)如果并非所有观察值都==100,但存在平局(第5、6位具有相同的值),我想随机选择那些具有平局的观察值,并再次将一些观察值放入列表(指标)中,将其他观察值放入列表(星号)中。 3) 如果没有关系,则仅选择前 5 个观察值。我现在的主要问题是,如果我想在最底部的循环(包含所有列)上运行我的函数。不知何故,我总是只得到第一行作为结果...我想我不知何故不明白如何在循环内正确设置函数的变量名称...?

library(dplyr)
library(tidyverse)

remove(list = ls())


dataframe_test <- data.frame(
county_name = c("a", "b","c", "d","e", "f", "g", "h"),
column_test1 = c(100,100,100,100,100,100,50,50),
column_test2 = c(40,90,50,40,40,100,13,14),
column_test3 = c(100,90,50,40,30,40,100,50),
month = c("2020-09-01", "2020-09-01" ,"2020-09-01" ,"2020-09-01" ,"2020-09-01" ,"2020-09-01" ,"2020-08-01","2020-08-01"))


choose_top_5 <- function(df, df_col_indicator, df_col_month, char_month, numb_top, df_col_county) {

### enquo / ensym / deparse
df_col_indicator_enquo <- enquo(df_col_indicator)
df_col_indicator_ensym <- ensym(df_col_indicator)

df_col_month_ensym <- ensym(df_col_month)
df_col_month_enquo = enquo(df_col_month)


### filter month and top 5 observations
df_top <- df %>%
filter(!!df_col_month_ensym == char_month) %>%
slice_max(!!df_col_indicator_ensym, n = numb_top) %>%
select(!!df_col_county, !!df_col_month_ensym, !!df_col_indicator_ensym)


### if there are more than "numb_top" values and all equals to 100 --> randomly pick "numb_top"
if (nrow(df_top) > numb_top &
sum(df_top[ , df_col_indicator ]) == 100*nrow(df_top) ) {

## randomly pick "numb_top" out of all
random_shuffle <- df_top[sample(nrow(df_top)),]
indicator <- random_shuffle[1:numb_top,]
asterisk <- random_shuffle[(numb_top+1):nrow(random_shuffle),]

## return "numb_top" and put names of others in asterisk
return_list <- list(indicator, asterisk)


### if there are more than "numb_top" values but not all 100 (e.g. 100, 100, 100, 99, 99, 99)
## --> pick randomly 99 values
} else if (nrow(df_top) > numb_top) {

### filter for all observations that have the same value as "numb_top"
df_treshold <- df_top %>%
filter(!!df_col_indicator_ensym == df_top[numb_top, df_col_indicator])

## randomly shuffle the observations
random_shuffle <- df_treshold[sample(nrow(df_treshold)),]

## combine observations again an pick "numb_top"
combine <- rbind(df_top[1:(nrow(df_top)-nrow(df_treshold)), ], random_shuffle)
indicator <- combine[1:numb_top,]
asterisk <- combine[(numb_top+1):nrow(combine),]

## return "numb_top" and put names of others in asterisk
return_list <- list(indicator, asterisk)

### if there are not more than "numb_top" values
} else {


indicator <- df_top
asterisk <- NA

## return "numb_top", asterisk is NA
return_list <- list(indicator, asterisk)
}

return(return_list)


}



### function for 1 column
a=choose_top_5(df = dataframe_test, df_col_indicator = "column_test3",
df_col_month = "month", char_month = "2020-09-01", numb_top = 5,
df_col_county = "county_name")
a



### function over all columns and store in list

all_indicators <- c("column_test1","column_test2","column_test3")

my_list <- list()

for (i in all_indicators) {

my_list[[i]] <- choose_top_5(df = dataframe_test, df_col_indicator = i,
df_col_month = "month", char_month = "2020-09-01", numb_top = 5,
df_col_county = "county_name")
}

my_list

最佳答案

添加到上面的 Allans 答案中:

通常,您不能在不支持准引用的函数内使用强制运算符!!准引用。然而,正如莱昂内尔·亨利指出的herehere即将推出的 {rlang} 版本可能会包含一个名为 blast() 的函数,用于立即求值的准引用。下面我用你的例子。在最后一行中,您可以看到如何在本身不支持准引用的基本 R 函数中使用 !!

library(tidyverse)
library(rlang)

### define dataframe
dataframe_test <- data.frame(
column_test = c(100,99,99,90,89,50),
month_test = c("2020-09-01", "2020-09-01","2020-09-01", "2020-09-01","2020-10-01","2020-10-01")
)

blast <- function(expr, env = caller_env()) {
eval_bare(enexpr(expr), env)
}

test_function <- function(df, df_col_indicator, df_col_month, char_month) {

df_col_indicator_enquo <- enquo(df_col_indicator)
df_col_indicator_ensym <- ensym(df_col_indicator)
df_col_month_enquo <- enquo(df_col_month)

temp <- df %>%
filter(!!df_col_month_enquo == char_month) %>%
slice_max(!!df_col_indicator_enquo, n = 3) %>%
filter(!!df_col_indicator_enquo == df %>%
select(!!df_col_indicator_enquo) %>%
pluck(1, 2))

# with `blast()` we can use the forcing operator !! inside sum(`$`...)
blast(sum(`$`(temp, !! df_col_indicator_ensym)))
}

test_function(df = dataframe_test, column_test, month_test , "2020-09-01")
#> [1] 198

reprex package于2020年11月5日创建(v0.3.0)

关于r - 函数内 enquo() 和 toString() 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64692609/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com