在R中更改动态创建的变量的值

时间:2014-02-05 12:54:49

标签: r

我通过以下方式在函数中创建了一些动态变量:

someIntegers <- c(4,2,5,7,1,3)
for (i in 1:length(someIntegers))
  assign(paste0("newVector", i), vector("numeric", someIntegers[i]))

我想更改这些动态创建的向量的值:

for(i in 1:length(someIntegers)) {
  for(j in 1:someIntegers[i]) {
    # I want to change the values of each of the dynamically created variables here
    assign(paste0("newVector", i, "[", j, "]"), rnorm(1, 0, 1))  # A small edit done here
    # This above line is not giving expected result
  }
}

所以我的问题是,如何更改动态创建的R变量中的值?在这种情况下,我想单独更改动态创建的向量的值newVector1newVector2等。

感谢。

3 个答案:

答案 0 :(得分:2)

使用list比使用assign更好。 我们还可以使用lapplysetNameslist2env

组合这两个步骤
someIntegers <- c(4,2,5,7,1,3)
vect_list <- setNames(
    lapply(someIntegers, function(l) rnorm(n = l, mean = 0, sd = 1)),
           paste0("newVector", seq_along(someIntegers))
    )

list2env(vect_list, envir = .GlobalEnv)
newVector1
## [1] -0.768529  0.791715 -0.050577 -1.246495

newVector5
## [1] -0.60301

如果你想分开这两个步骤:

1 - 创建不同长度的空载体

someIntegers <- c(4,2,5,7,1,3)
vect_list <- setNames(
    lapply(someIntegers, function(l) vector(mode = "numeric", length = l)),
           paste0("newVector", seq_along(someIntegers))
    )

str(vect_list)
## List of 6
##  $ newVector1: num [1:4] 0 0 0 0
##  $ newVector2: num [1:2] 0 0
##  $ newVector3: num [1:5] 0 0 0 0 0
##  $ newVector4: num [1:7] 0 0 0 0 0 0 0
##  $ newVector5: num 0
##  $ newVector6: num [1:3] 0 0 0

2 - 填充不同元素

vect_list <- lapply(vect_list,
                    function(x) "[<-"(seq_along(x), rnorm(length(x))))
str(vect_list)
## List of 6
##  $ newVector1: num [1:4] -0.0775 0.4195 -0.8565 -1.7445
##  $ newVector2: num [1:2] -2.069 -0.209
##  $ newVector3: num [1:5] -1.07 1.26 -1.04 1.97 -2.48
##  $ newVector4: num [1:7] 0.0529 0.3997 -2.2187 -1.3695 0.061 ...
##  $ newVector5: num -0.0461
##  $ newVector6: num [1:3] -0.999 -1.082 -0.789

答案 1 :(得分:0)

您可以创建包含变量的列表:

vectors <- mget(ls(pattern='newVector'))

然后您可以轻松访问这样的矢量元素,例如访问第一个和第二个元素:

vectors[c('newVector1','newVector2')]
$newVector1
[1] 0 0 0 0

$newVector2
[1] 0 0

要为每个元素指定一个新值,可以使用lapply,例如,我在为列表的每个向量的第一个元素指定10:

lapply(vectors ,function(x){x[1] <- 10;x})

$newVector1
[1] 10  0  0  0
$newVector2
[1] 10  0
$newVector3
[1] 10  0  0  0  0
$newVector4
[1] 10  0  0  0  0  0  0
$newVector5
[1] 10
$newVector6
[1] 10  0  0

答案 2 :(得分:0)

虽然我同意其他人对使用列表进行此类事情所说的内容,仅供参考,但这是一种(非推荐)方式来做你想做的事情,即分配给“动态”变量在顶级环境中:

for(i in 1:length(someIntegers)) {
  for(j in 1:someIntegers[i]) {
    eval(parse(text=paste0("newVector", i, "[", j, "] <- ", runif(1, 0, 1))))
} }

这就是你所期望的:

> newVector1
[1] 0.8895393 0.6928034 0.6405068 0.9942698
> newVector2
[1] 0.6557058 0.7085305
> newVector3
[1] 0.5440660 0.5941420 0.2891597 0.1471136 0.9630242
> newVector4
[1] 0.90229905 0.69070528 0.79546742 0.02461368 0.47779597 0.75845954 0.21640794
> newVector5
[1] 0.318181
> newVector6
[1] 0.2316258 0.1428000 0.4145463

我不知道如何使用assign执行此操作,因为我不知道如何使用assign分配子集。请注意,执行此操作的更好方法是执行assign(paste0("newVector", i), runif(someIntegers[i], 0, 1))以避免eval步骤,因为对于此玩具示例,您可以生成全长随机向量并分配整个变量,但我提供如果您需要访问特定索引,则使用另一种方法。

请注意,R提供了一系列函数来操作列表项(lapply是其中之一),因此您应该考虑将变量指定为列表元素,而不是作为顶级变量。我在这里展示。

最后一点说明。如果您要使用parse,则需要确保完全控制您评估的表达式(即不接受来自Web的输入并在不进行检查的情况下对其进行评估,因为有人可能会注入恶意命令)。