-1

I have:

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

I am trying to do:

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

Problems:

  1. paste(c('z$x'),i,sep="") yields "z$x1", "z$x1" instead of calling the actual values. I need the expression to be evaluated. I tried as.numeric, eval. Neither seemed to work.

  2. paste(c('N'),i,sep="") yields "N1", "N2". I need the expression to be merely used as name. If I try to assign it a value such as paste(c('N'),5,sep="") -> 5, ie "N5" -> 5 instead of N5 -> 5, I get target of assignment expands to non-language object.

This task is pretty trivial since I can simply do:

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

etc, but I want to learn something new

4

3 回答 3

2

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

但是,既然你说你想学习新东西,你可以玩弄parseand substitute

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

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

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

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

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

下一个语言对象是call. 这是一个递归对象,实现为 a list,其元素是常量、符号或另一个调用。第一个元素不能是常量,因为它必须计算为function将被调用的实数。其他元素是此函数的参数。

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

示例:代码行将f(x, y+z, 2)被解析为 4 个元素的列表,第一个是f(作为符号),第二个是x(另一个符号),第三个是 another 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="")))))

内部替代创建callsz$x1z$x2。外部替代将此调用作为赋值的标记,并将符号N1N2作为值。

parse结果是expression,并且substitutecall。两者都可以传递给以eval获得相同的结果。

最后一点:我再说一遍,所有这些都是为了作为一个教学示例,以帮助理解语言的内部工作原理,但是使用and远非良好的编程实践,除非真的别无选择。parsesubstitute

于 2013-04-12T01:47:50.360 回答
2

Adata.frame是一个named 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
于 2013-04-12T01:55:20.530 回答
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
于 2013-04-11T21:44:23.577 回答