2015-06-29 138 views
0

对R仍然比较新。尝试在循环中使用动态变量,但遇到各种问题。最初的代码看起来是这样的(但更大)循环中的R变量名,get等

data.train$Pclass_F <- as.factor(data.train$Pclass) 
data.test$Pclass_F <- as.factor(data.test$Pclass) 

,我正在努力建设成一个圈,想象这样的事情

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    i$Pclass_F <- as.factor(i$Pclass) 
} 

不工作。一些研究表明,为了将字符串datalist转换为变量,我需要使用get函数。所以我的下一次尝试是

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i$Pclass_F) <- as.factor(get(i$Pclass)) 
} 

哪些仍然不工作Error in i$Pclass : $ operator is invalid for atomic vectors。试过

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i)$Pclass_F <- as.factor(get(i)$Pclass) 
} 

哪些仍然不起作用Error in get(i)$Pclass_F <- as.factor(get(i)$Pclass) : could not find function "get<-"。即使尝试过

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i[Pclass_F]) <- as.factor(get(i[Pclass])) 
} 

哪个仍然不起作用Error in get(i[Pclass]) : object 'Pclass' not found。她试图

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i)[Pclass_F] <- as.factor(get(i)[Pclass]) 
} 

仍然不起作用Error in '[.data.frame'(get(i), Pclass) : object 'Pclass' not found

现在意识到,我从未纳入的数据,所以没有人可以运行此本身,而只是表明这不是一个数据问题

> class(data.train$Pclass) 
[1] "integer" 
> class(data.test$Pclass) 
[1] "integer" 
> datalist 
[1] "data.train" "data.test" 
+8

停止在'get'周围构建代码。将它从词典中删除,直到你对R更好。只要你认为“动态变量”,就停下来建立一个名单。把它们放在一个实际的列表中,并使用索引:'L < - list(data.train = data.train,data.test = data.test)'。 – joran

+1

我同意这是可怕的编码。根本不是我第一次看到这个。我真的很想知道这些坏习惯是从哪里来的,以及他们如何为OP做出“直觉”和“自然”。我认为这是一个需要解决的问题(也是主要问题)。 –

+2

@ColonelBeauvel我在OP上不会太难。成为初学者通常意味着只是试图找到“有效”的东西,并且了解它在过程中是否“优秀”。我发现这个特别的问题令人沮丧,因为它经常出现,但每个人的用例是如此不同,以至于写出一个能够有效地引导人们远离“获取”和“分配”的单一综合资源是非常困难的。 – joran

回答

4

的问题与R中的数据框和大多数其他对象的处理方式有关。在许多编程语言中,对象(或至少可以)通过引用传递给函数。在C++中,如果将指向对象的指针传递给操作该对象的函数,则会修改原始对象。这不是当一个对象被创建类似这样的事情在R.

大部分的工作方式:

x <- list(a = 5, b = 9) 

,然后复制这样的:

y <- x 

最初yx将指向RAM中的同一个对象。但只要y被修改,就会创建一个副本。因此,分配y$c <- 12x没有影响。

get()不会返回指定对象的方式,如果不先将其指定给另一个变量(这意味着原始变量保持不变),可以对其进行修改。

在R中这样做的正确方法是将数据帧存储在名为list中。然后,您可以遍历列表并使用替换语法来更改列。

datalist <- list(data.train = data.train, data.test = data.test) 
for (df in names(datalist)){ 
    datalist[[df]]$Pclass_F <- as.factor(datalist[[df]]$Pclass_F) 
} 

您还可以使用:

datalist <- setNames(lapply(list(data.train, data.test), function(data) { 
    data$Pclass_Fb <- as.factor(data$Pclass_Fb) 
    data 
}), c("data.train", "data.test")) 

这是使用lapply来处理列表中的每个成员,返回与修改后的列的新名单。

从理论上讲,您可以通过在全球环境中使用[[运营商来实现您原本试图做的事情,但这将是一种非常规的做事方式,可能会在以后导致混淆。

+0

Thanks @Nick KI had拿出类似的东西,但在第一个例子中,它将列添加到列表中的数据框,而不是实际的数据框本身。如果我看一下'head(data.train)',我没有看到新列,但是如果我看'head(datalist [[1]])'我可以。 –

+3

@SC。这正是我试图解决的问题。在全球环境中没有使用'['',在全球环境中没有办法通过数据框架实现你想要的。您需要将它们存储在一个列表或环境中,并且通常我会为此用例使用一个列表。然后你仍然可以将它们称为'datalist $ data.train',并在循环中使用它们,如下所示。或者,你当然也可以为每个data.frame使用单独的语句(就像在你的答案的开始处),并且如果你正在处理一个函数中的那段代码中的多个列。 –

+0

谢谢@尼克。我想@joran也在说这些,但我不明白。所以在这种情况下,list'datalist'成为我的主要数据结构。这是一个我没有想到的有趣概念。它会使一些名字相当长'datalist $ data.train $ Pclass'等,但它应该工作。我认为这是最好的练习,而且我有一个很好的习惯? –