根据包含这些对象信息的输入文件在 R 中创建新对象
Create new objects in R based on input file with information on these objects
假设我有以下查找 table:
object_lookup <- data.frame(name = c(new_var_1, new_var_2, new_var_2),
value = c(7, "ABC", "XYZ"),
type = c("numeric", "character", "character"))
我现在想遍历该列表并根据 name
值创建对象,根据 value
列为它们分配值,并希望确保它们具有提供的类型在 type
.
我知道如何使用 assign
一次创建一个新对象,但我正在努力解决 a) 自动化流程和 b) 确保类型正确以及 c) 如何处理应该分配多个值的情况。我在这里想到了某种应用功能?
……喜欢 apply(object_lookup, 1, function(x) {assign(name, value); if (type == "numeric) as.numeric(x)}
最终,我想在该示例中有两个新的 R 对象:
new_var_1 <- c(7) # numeric
new_var_2 <- c("ABC", "XYZ") # character
有什么想法吗?
你在 data.frame
中的第一列应该是字符向量然后你可以尝试这样的事情:
library(dplyr)
library(purrr)
object_lookup %>%
mutate(across(everything(), as.character)) %>%
group_by(name) %>%
summarise(value = list(value), type = unique(type)) %>%
{if(any(count(., name)$n > 1)) stop("wrong input") else .} %>%
mutate(value = map2(value, type, ~do.call(paste0("as.", .y), args = list(.x)))) %>%
select(name, value) %>%
pwalk(~assign(.x, .y, envir = globalenv()))
stop
输入错误是否存在(同变量不同类型)
我可以推荐一种更详细的方法吗?代码中的空气和清晰度没有任何问题。程序的用途一目了然,步骤简单,可以根据未来的新规范轻松灵活地进行更改。
希望您也可以使用 tibble 而不是 data.frame。这样做的好处是不强迫您的值是字符,可能会产生不需要的副作用。 (字符和数字都可以,我不知道还有什么可能!)
object_lookup <- tibble(
name = c("new_var_1", "new_var_2", "new_var_2"),
value = list(7, "ABC", "XYZ"),
type = c("numeric", "character", "character")
)
known.types <- list(
numeric = as.numeric,
character = as.character
)
for( vname in unique( object_lookup$name ) ) {
i <- object_lookup$name %in% vname
vtype <- unique( object_lookup$type[i] )
if( length( vtype ) > 1 ) {
stop( "A variable can only have one type: '", vname, "' failed to process.")
}
assign(
vname,
known.types[[vtype]]( unlist( object_lookup$value[i], recursive=FALSE ) )
)
}
当信任可用输入并根据可用输入创建内容时,建议采用一些故障安全机制。例如,上面的代码永远不会 运行 除非类型存在于声明类型列表中,它还提供了一个转换器,这是一个很好的安全措施。如果你不需要转换器,你也可以把 I
放在那里,例如 weirdobject = I
in known.types.
假设我有以下查找 table:
object_lookup <- data.frame(name = c(new_var_1, new_var_2, new_var_2),
value = c(7, "ABC", "XYZ"),
type = c("numeric", "character", "character"))
我现在想遍历该列表并根据 name
值创建对象,根据 value
列为它们分配值,并希望确保它们具有提供的类型在 type
.
我知道如何使用 assign
一次创建一个新对象,但我正在努力解决 a) 自动化流程和 b) 确保类型正确以及 c) 如何处理应该分配多个值的情况。我在这里想到了某种应用功能?
……喜欢 apply(object_lookup, 1, function(x) {assign(name, value); if (type == "numeric) as.numeric(x)}
最终,我想在该示例中有两个新的 R 对象:
new_var_1 <- c(7) # numeric
new_var_2 <- c("ABC", "XYZ") # character
有什么想法吗?
你在 data.frame
中的第一列应该是字符向量然后你可以尝试这样的事情:
library(dplyr)
library(purrr)
object_lookup %>%
mutate(across(everything(), as.character)) %>%
group_by(name) %>%
summarise(value = list(value), type = unique(type)) %>%
{if(any(count(., name)$n > 1)) stop("wrong input") else .} %>%
mutate(value = map2(value, type, ~do.call(paste0("as.", .y), args = list(.x)))) %>%
select(name, value) %>%
pwalk(~assign(.x, .y, envir = globalenv()))
stop
输入错误是否存在(同变量不同类型)
我可以推荐一种更详细的方法吗?代码中的空气和清晰度没有任何问题。程序的用途一目了然,步骤简单,可以根据未来的新规范轻松灵活地进行更改。
希望您也可以使用 tibble 而不是 data.frame。这样做的好处是不强迫您的值是字符,可能会产生不需要的副作用。 (字符和数字都可以,我不知道还有什么可能!)
object_lookup <- tibble(
name = c("new_var_1", "new_var_2", "new_var_2"),
value = list(7, "ABC", "XYZ"),
type = c("numeric", "character", "character")
)
known.types <- list(
numeric = as.numeric,
character = as.character
)
for( vname in unique( object_lookup$name ) ) {
i <- object_lookup$name %in% vname
vtype <- unique( object_lookup$type[i] )
if( length( vtype ) > 1 ) {
stop( "A variable can only have one type: '", vname, "' failed to process.")
}
assign(
vname,
known.types[[vtype]]( unlist( object_lookup$value[i], recursive=FALSE ) )
)
}
当信任可用输入并根据可用输入创建内容时,建议采用一些故障安全机制。例如,上面的代码永远不会 运行 除非类型存在于声明类型列表中,它还提供了一个转换器,这是一个很好的安全措施。如果你不需要转换器,你也可以把 I
放在那里,例如 weirdobject = I
in known.types.