在嵌套对象的函数环境中找不到对象
Object not found in function environment for nested objects
我有一个代码片段,我正试图将其转换为一个函数。此函数应该在手动输入字段中查找潜在的拼写错误。该代码段有效,您可以使用 tidyverse 包中的 starwars 数据像这样尝试:
require(tidyverse)
require(rlang) # loaded for {{ to force function arguments as well as the with_env() function
require(RecordLinkage) # loaded for the jarowinkler() function
starwars_cleaning <- starwars %>%
add_count(name, name = "Freq_name") %>% # this keeps track of which spelling is more frequent
distinct(name, .keep_all = T) %>% # this prevents duplicated comparisons and self-comparisons
nest_by(homeworld, .key = ".Nest") %>%
mutate(Mapped = list(imap_dfr(.x = .Nest$name,
.f = ~jarowinkler(str1 = .x,
str2 = .Nest$name[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list(.Nest$name[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
)))
该函数应接受嵌套在(省略号)上的变量和查找潜在拼写错误匹配项的变量作为参数。现在,它看起来像这样:
string_matching <- function(.df, .string_col, ...){
.df$.tmp_string <- .df %>% select({{.string_col}})
.df <- .df %>%
add_count(.tmp_string, name = "Freq_name") %>%
distinct(.tmp_string, .keep_all = T) %>%
nest_by(..., .key = ".Nest") %>%
mutate(Mapped_n = list(with_env(env = current_env(), # same error with or without specifying the execution environment for imap
expr = imap_dfr(.x = .Nest$.tmp_string,
.f = ~jarowinkler(str1 = .x,
str2 = .Nest$.tmp_string[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list(.Nest$.tmp_string[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
)
))
)
return(.df)
}
starwars %>%
string_matching(name, homeworld)
关于 starwars 数据,它显然不是很有用。我削减了这段代码的一些功能以获得 MWE——但这就是我的想法。当我将代码像这样包装在一个函数中时,它 returns invalid argument to unary operator
(显然是由 [-.y]
引起的)。我在阅读 后尝试了 force()
命令,因为这个问题显然经常出现。由于当前错误和 post,我认为问题可能与导致 imap_dfr()
以某种方式丢失数据的功能环境有关。我试图将对 map 的调用包装在 with_env()
中并指示它使用函数环境而不是它自己的环境。我还尝试通过将中间对象分配给全局环境来分解函数,以便可以在函数的映射步骤中找到它:
assign(x = "TEMP", value = .df$.Nest, envir = global_env())
这让我遇到了同样的“一元运算符”错误。我不确定接下来要尝试什么。我好像在兜圈子。任何关于导致此问题的原因以及如何解决它的见解将不胜感激。
我认为您所指的 post 与此处无关。我认为您的问题与执行环境无关。问题实际上是您如何处理将变量传递给您的函数。当您创建 tmp_string
时,您调用的是 select()
,它返回一个 tibble 而不是列值的向量。相反,使用 pull()
来提取这些值。
string_matching <- function(.df, .string_col, ...){
.df$.tmp_string <- .df %>% pull({{.string_col}})
.df <- .df %>%
add_count(.tmp_string, name = "Freq_name") %>%
distinct(.tmp_string, .keep_all = T) %>%
nest_by(..., .key = ".Nest") %>%
mutate(Mapped_n = list(with_env(env = current_env(), # same error with or without specifying the execution environment for imap
expr = imap_dfr(.x = .Nest$.tmp_string,
.f = ~jarowinkler(str1 = .x,
str2 = .Nest$.tmp_string[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list(.Nest$.tmp_string[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
)
))
)
return(.df)
}
或者您可以编写代码来完全避免需要该临时列
string_matching <- function(.df, .string_col, ...){
col <- rlang::ensym(.string_col)
.df <- .df %>%
add_count(!!col, name = "Freq_name") %>%
distinct(!!col, .keep_all = T) %>%
nest_by(..., .key = ".Nest") %>%
mutate(Mapped_n = list(imap_dfr(.x = .Nest %>% pull(!!col),
.f = ~jarowinkler(str1 = .x,
str2 = (.Nest %>% pull(col))[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list((.Nest %>% pull(col))[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
))
)
return(.df)
}
我有一个代码片段,我正试图将其转换为一个函数。此函数应该在手动输入字段中查找潜在的拼写错误。该代码段有效,您可以使用 tidyverse 包中的 starwars 数据像这样尝试:
require(tidyverse)
require(rlang) # loaded for {{ to force function arguments as well as the with_env() function
require(RecordLinkage) # loaded for the jarowinkler() function
starwars_cleaning <- starwars %>%
add_count(name, name = "Freq_name") %>% # this keeps track of which spelling is more frequent
distinct(name, .keep_all = T) %>% # this prevents duplicated comparisons and self-comparisons
nest_by(homeworld, .key = ".Nest") %>%
mutate(Mapped = list(imap_dfr(.x = .Nest$name,
.f = ~jarowinkler(str1 = .x,
str2 = .Nest$name[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list(.Nest$name[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
)))
该函数应接受嵌套在(省略号)上的变量和查找潜在拼写错误匹配项的变量作为参数。现在,它看起来像这样:
string_matching <- function(.df, .string_col, ...){
.df$.tmp_string <- .df %>% select({{.string_col}})
.df <- .df %>%
add_count(.tmp_string, name = "Freq_name") %>%
distinct(.tmp_string, .keep_all = T) %>%
nest_by(..., .key = ".Nest") %>%
mutate(Mapped_n = list(with_env(env = current_env(), # same error with or without specifying the execution environment for imap
expr = imap_dfr(.x = .Nest$.tmp_string,
.f = ~jarowinkler(str1 = .x,
str2 = .Nest$.tmp_string[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list(.Nest$.tmp_string[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
)
))
)
return(.df)
}
starwars %>%
string_matching(name, homeworld)
关于 starwars 数据,它显然不是很有用。我削减了这段代码的一些功能以获得 MWE——但这就是我的想法。当我将代码像这样包装在一个函数中时,它 returns invalid argument to unary operator
(显然是由 [-.y]
引起的)。我在阅读 force()
命令,因为这个问题显然经常出现。由于当前错误和 post,我认为问题可能与导致 imap_dfr()
以某种方式丢失数据的功能环境有关。我试图将对 map 的调用包装在 with_env()
中并指示它使用函数环境而不是它自己的环境。我还尝试通过将中间对象分配给全局环境来分解函数,以便可以在函数的映射步骤中找到它:
assign(x = "TEMP", value = .df$.Nest, envir = global_env())
这让我遇到了同样的“一元运算符”错误。我不确定接下来要尝试什么。我好像在兜圈子。任何关于导致此问题的原因以及如何解决它的见解将不胜感激。
我认为您所指的 post 与此处无关。我认为您的问题与执行环境无关。问题实际上是您如何处理将变量传递给您的函数。当您创建 tmp_string
时,您调用的是 select()
,它返回一个 tibble 而不是列值的向量。相反,使用 pull()
来提取这些值。
string_matching <- function(.df, .string_col, ...){
.df$.tmp_string <- .df %>% pull({{.string_col}})
.df <- .df %>%
add_count(.tmp_string, name = "Freq_name") %>%
distinct(.tmp_string, .keep_all = T) %>%
nest_by(..., .key = ".Nest") %>%
mutate(Mapped_n = list(with_env(env = current_env(), # same error with or without specifying the execution environment for imap
expr = imap_dfr(.x = .Nest$.tmp_string,
.f = ~jarowinkler(str1 = .x,
str2 = .Nest$.tmp_string[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list(.Nest$.tmp_string[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
)
))
)
return(.df)
}
或者您可以编写代码来完全避免需要该临时列
string_matching <- function(.df, .string_col, ...){
col <- rlang::ensym(.string_col)
.df <- .df %>%
add_count(!!col, name = "Freq_name") %>%
distinct(!!col, .keep_all = T) %>%
nest_by(..., .key = ".Nest") %>%
mutate(Mapped_n = list(imap_dfr(.x = .Nest %>% pull(!!col),
.f = ~jarowinkler(str1 = .x,
str2 = (.Nest %>% pull(col))[-.y]) %>%
list() %>%
tibble(Score_n = ., Match_n = list((.Nest %>% pull(col))[-.y]),
Freq_n = list(.Nest$Freq_name[-.y]))
))
)
return(.df)
}