根据包含这些对象信息的输入文件在 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.