将字符向量转换为R中的数字向量以进行值赋值?

时间:2013-04-11 21:18:18

标签: r math syntax statistics

我有:

z = data.frame(x1=a, x2=b, x3=c, etc)

我正在尝试:

for (i in 1:10)
{
    paste(c('N'),i,sep="") -> paste(c('z$x'),i,sep="")
}

问题:

  1. paste(c('z$x'),i,sep="")会产生"z$x1", "z$x1"而不是调用实际值。我需要表达式进行评估。我试过了as.numeric, eval。似乎都没有效果。

  2. paste(c('N'),i,sep="")收益"N1", "N2"。我需要将表达式仅用作名称。如果我尝试为其分配paste(c('N'),5,sep="") -> 5,即"N5" -> 5而不是N5 -> 5,我会将分配目标扩展为非语言对象。

  3. 这项任务非常简单,因为我可以这样做:

    N1 = x1 ...... N2 = x2 ......

    等,但我想学习新的东西

3 个答案:

答案 0 :(得分:2)

我建议使用类似for( i in 1:10 ) z[,i] <- N[,i] ...

的内容

但是,既然你说你想学习新的东西,你就可以使用parsesubstitute

注意:这些小工具很有趣,但有经验的用户(不是我)会避开它们。

这称为“计算语言”。它非常有趣,它有助于理解R的工作方式。让我试着介绍一下:

基本语言构造是一个常量,如数字或字符向量。它是微不足道的,因为它与它的“未评估”版本没有什么不同,但它是更复杂表达的构建块之一。

(官方)基本语言对象是symbol,也称为name。它只是指向另一个对象的指针,即标识可能存在或不存在的另一个对象的标记。例如,如果您运行x <- 10,则x是一个引用值10的符号。换句话说,评估符号x会产生数字向量10。评估不存在的符号会产生错误。

符号看起来像字符串,但不是。您可以使用as.symbol("x")将字符串转换为符号。

下一个语言对象是call。这是一个递归对象,实现为list,其元素是常量,符号或其他调用。第一个元素必须是常量,因为它必须求值为将被调用的实际function。其他元素是此函数的参数。

如果第一个参数未计算到现有函数,则R将抛出Error: attempt to apply non-functionError: could not find function "x"(如果第一个参数是未定义的符号或指向函数以外的其他参数)

示例:代码行f(x, y+z, 2)将被解析为4个元素的列表,第一个是f(作为符号),第二个是x(另一个符号),第三个是另一个call,第四个是数字常量。第三个元素y+z只是一个带有两个参数的函数,因此它会解析为三个名称的列表:'+'yz

最后,还有expression对象,它是一个调用/符号/常量列表,用于逐个评估。

你会在这里找到很多信息:

https://github.com/hadley/devtools/wiki/Computing-on-the-language

好的,现在让我们回到你的问题: - )

你所尝试的东西不起作用,因为paste的输出是一个字符串,并且赋值函数期望作为其第一个参数,评估为一个符号,可以创建或修改。或者,第一个参数也可以评估与替换函数关联的调用。这些有点棘手,但它们由赋值函数本身处理,而不是由解析器处理。

您看到的错误消息target of assignment expands to non-language object由赋值函数触发,正是因为您的目标求值为字符串。

我们可以修复在正确的位置建立一个包含所需符号的呼叫。最“强力”的方法是将所有内容放在一个字符串中并使用解析:

parse(text=paste('N',i," -> ",'z$x',i,sep=""))

另一种方法是使用substitute

substitute(x -> y, list(x=as.symbol(paste("N",i,sep="")), y=substitute(z$w, list(w=paste("x",i,sep="")))))

内部替代品会创建call s z$x1z$x2等。外部替代品将此调用作为分配的标记,以及符号N1,{ {1}}等作为值。

N2会在parse中生成expressionsubstitute。两者都可以传递给call以获得相同的结果。

最后一点注意事项:我重申所有这些都是作为一个教学示例,以帮助理解语言的内部工作原理,但是从良好的编程习惯中使用{{1 }和eval,除非真的没有其他选择。

答案 1 :(得分:2)

data.framenamed list。这通常是一种很好的做法,并且惯用R-ish不要在全局环境中拥有大量对象,而是在列表中包含相关(或类似)对象并使用lapply等。

您可以使用list2env将列表中的命名元素(data.frame中的列)多重分配到全局环境

DD <- data.frame(x = 1:3, y = letters[1:3], z = 3:1)
list2env(DD, envir = parent.frame())
## <environment: R_GlobalEnv>
## ta da, x, y and z now exist within the global environment 
x
## [1] 1 2 3
y
## [1] a b c
## Levels: a b c
z
## [1] 3 2 1

答案 2 :(得分:1)

我不确定你想要完成什么。但这是一个猜测:

### Create a data.frame using the alphabet
data <- data.frame(x = 'a', y = 'b', z = 'c')

### Create a numerical index corresponding to the letter position in the alphabet
index <- which(tolower(letters[1:26]) == data[1, ])

### Use an 'lapply' to apply a function to every element in 'index'; creates a list
val <- lapply(index, function(x) {
    paste('N', x, sep = '')
})

### Assign names to our list
names(val) <- names(data)

### Observe the result
val$x