Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用R以编程方式命名对象的最佳方法?_R_Loops_Variable Assignment - Fatal编程技术网

使用R以编程方式命名对象的最佳方法?

使用R以编程方式命名对象的最佳方法?,r,loops,variable-assignment,R,Loops,Variable Assignment,我在数据集上运行各种建模算法。通过将我的输入变量与我的回答一次一个地建模,我得到了最好的结果,例如: model <- train(y ~ x1 + x2 + ... + xn, ...) 然而,当我加载模型时,它将被称为model 我还没有找到一个好的方法来保存具有相应名称的模型,以便稍后尝试并引用它。我发现可以将对象分配给字符串,如下所示: assign(paste("./models/model_rf_", names(data_resp)[i], ".rda", sep = ""

我在数据集上运行各种建模算法。通过将我的输入变量与我的回答一次一个地建模,我得到了最好的结果,例如:

model <- train(y ~ x1 + x2 + ... + xn, ...)
然而,当我加载模型时,它将被称为model

我还没有找到一个好的方法来保存具有相应名称的模型,以便稍后尝试并引用它。我发现可以将对象分配给字符串,如下所示:

assign(paste("./models/model_rf_", names(data_resp)[i], ".rda", sep = ""), train(...))
但在保存对象时,我仍然需要了解如何引用该对象:

save(???, file = ...)
我不知道如何用自定义名称来调用对象

最后,即使是加载也存在问题。我尝试分配model_name,load./model.rda,但结果对象string最终只包含一个对象名model的字符串

在环顾四周的过程中,我发现了一个似乎相关的问题,但我正试图找出如何将其应用于我的情况


我可以创建一个列表,列出数据中每个列名的名称和测量的响应,然后使用Lappy来使用train,但我仍然有点困惑于如何动态引用新对象名以保持结果模型。

这个答案涉及大量猜测,但我认为这可能会有所帮助:

# get a vector with the column names in data_resp
modNames <- colnames( data_resp )

# create empty list
models <- as.list( NULL )

# iterate through your columns and assign the result as list members
for( n in modNames )
{
  models[[n]] <- train(data_pred_scale[!is.na(data_resp[, n]), ],  ### this may need modification, can't test without data
                 data_resp[!is.na(data_resp[, n]), n],
                 method = "rf",
                 tuneGrid = data.frame(.mtry = c(3:6)),
                 nodesize = 3,
                 ntrees = 500)
}

# save the whole bunch
save( models, file = "models.rda" )

现在,只需使用load models.rda,您就可以检索这一个对象,以及包含所有模型的列表,并使用列表表示法将其命名为模型[[1]]或列名,例如模型[[first]]。

保存模型时,保存另一个名为“name”的对象,该对象是您要命名的对象的字符串:

> d=data.frame(x=1:10,y=rnorm(10))
> model=lm(y~x,data=d)
> name="m1"
> save(model,name,file="save1.rda")
> d=data.frame(x=1:10,y=rnorm(10))
> model=lm(y~x,data=d)
> name="m2"
> save(model,name,file="save2.rda")
现在,每个文件都知道它希望调用其结果对象的内容。你怎么把它装回去的?加载到新环境中,并分配:

> e=new.env()
> load("save1.rda",env=e)
> assign(e$name,e$model)
> summary(m1)

Call:
lm(formula = y ~ x, data = d)
您现在可以安全地rm或重用“e”对象。当然,您可以将其包装到函数中:

> blargh=function(f){e=new.env();load(f,env=e);assign(e$name,e$model,.GlobalEnv)}
> blargh("save2.rda")
> m2

Call:
lm(formula = y ~ x, data = d)
注意,这是一件双重的坏事——首先,您可能应该将所有模型存储在一个文件中,作为一个带有名称的列表。其次,这个函数有副作用,如果你已经有了一个名为m2的对象,它就会被踩死

像这样使用赋值几乎总是一个符号?你应该使用列表来代替


B

我认为关于使用循环执行此操作的其他答案非常好。我利用这一机会最终尝试更好地理解Lappy,因为许多关于如何做到这一点的StackOverflow问题最终建议使用列表和Lappy而不是循环

我真的很喜欢将训练的所有结果合并到一个列表中的想法,就像@vaettchen在他的循环中所做的那样,在思考如何使用一个列表时,我想到了这一点。首先,我需要列表形式的data.frame,每列一个条目。因为我并不真正使用列表,所以我四处寻找,直到尝试了as.listdf,这就像一个符咒

接下来,我想将我的train函数应用于我的测量响应变量列表的每个元素,因此我定义了如下函数:

# predictors are stored in data_pred
# responses are in data_resp (one per column)
# rows in data_pred/data_resp (perhaps obviously) match, one per observation

train_func <- function(y) { train(x = data_pred, y = y,
   method = "rf", tuneGrid = data.frame(.mtry = 3:6),
   ntrees = 500) }
令人惊奇的是,我发现模型的元素会自动命名到我在data_resp中的列名中,这真是太棒了。我将其与Shining软件包结合使用,因此用户可以非常轻松地从下拉列表中选择响应变量,该下拉列表可以存储响应变量名称,并执行以下操作:

predict(models[["resp_name"]], new_data)
我认为这比基于循环的方法要好得多,而且一切都恰到好处。我意识到这个问题是明确要求以编程方式命名变量的,因此,如果这迫使其他人以这种方式回答,而不是以更大的图景回答,我表示歉意。lapply的轻松表明,当至少在我看来有一个更好的解决方案存在时,我正试图强制一个特定的解决方案

奖励:我不知道列表可以是多维的,但在尝试时,似乎它们可以!这甚至更好,因为我使用了许多算法,我可以将所有内容存储在一个大列表对象中

 func_rf <- function(y) { train(x = data_pred, y = y,
     method = "rf", tuneGrid = data.frame(.mtry = 3),
     ntrees = 100) }

 # svmRadial method requires formula syntax to work with factors,
 # so the train function has to be a bit different
 # add `scale = F` since I had to preProcess the numeric vars ahead of time
 # and cbind to the factors. Without it, caret will try to scale the data
 # for you, which fails for factors

 func_svm <- function(y) { train(y ~ ., cbind(data_pred, y),
     method = "svmRadial", tuneGrid = data.frame(.C = 1, .sigma = .2),
     scale = F) }

 model_list <- list(NULL)
 model_list$rf <- lapply(as.list(data_resp), func_rf)
 model_list$svm <- lapply(as.list(data_resp), func_svm)

对此非常满意,希望它能使代码更高效、更快,我真的很喜欢最终得到的元对象,而不是一吨文件,每个模型/响应变量组合一个,我以后必须一次加载一个。

有点老问题,但仍然没有公认的答案。 据我所知,您需要以编程方式重命名变量并保存它,以便在重新加载时保留新名称。 试试这个:

saveWithName = function(var.name, obj){
  # var.name is a string with the name of the variable you want to assign
  # obj is any kind of R object (data.frame, list, etc.) you want to rename and save
  assign(var.name, obj)
  save(list=var.name, file=sprintf("model_%s.RData", var.name))
}

saveWithName("lab1", c(1,2))
saveWithName("lab2", c(3,4))
load("model_lab1.RData")
load("model_lab2.RData")

print(lab1)
#>[1] 1 2
print(lab2)
#[1] 3 4

只要阅读文档并记下第二个参数,就可以回答您关于save的具体问题。尝试使用saveRDS和readRDS。在这种情况下,它会简化很多事情。使用lappy时,上面的函数有效吗?我试图对trainControl做同样的事情,但运行Lappy时参数似乎没有通过。60091您能说得更具体一点吗?我已经有一段时间没用这个了,但我确实用过它。。。是的,它的工作原理如图所示。您是否试图创建trainControl对象列表,然后对其进行迭代以查看对结果模型的影响? 或者让Lappy迭代模型/数据,并引入一个trainControl对象作为训练参数的一部分?
 func_rf <- function(y) { train(x = data_pred, y = y,
     method = "rf", tuneGrid = data.frame(.mtry = 3),
     ntrees = 100) }

 # svmRadial method requires formula syntax to work with factors,
 # so the train function has to be a bit different
 # add `scale = F` since I had to preProcess the numeric vars ahead of time
 # and cbind to the factors. Without it, caret will try to scale the data
 # for you, which fails for factors

 func_svm <- function(y) { train(y ~ ., cbind(data_pred, y),
     method = "svmRadial", tuneGrid = data.frame(.C = 1, .sigma = .2),
     scale = F) }

 model_list <- list(NULL)
 model_list$rf <- lapply(as.list(data_resp), func_rf)
 model_list$svm <- lapply(as.list(data_resp), func_svm)
 predict(model_list[["svm"]][["response_variable"]], new_data)
saveWithName = function(var.name, obj){
  # var.name is a string with the name of the variable you want to assign
  # obj is any kind of R object (data.frame, list, etc.) you want to rename and save
  assign(var.name, obj)
  save(list=var.name, file=sprintf("model_%s.RData", var.name))
}

saveWithName("lab1", c(1,2))
saveWithName("lab2", c(3,4))
load("model_lab1.RData")
load("model_lab2.RData")

print(lab1)
#>[1] 1 2
print(lab2)
#[1] 3 4