所以我在R中有一个数据框,其中一列是几个因素的变量,我想为每个因子创建一些虚拟变量但是当我写一个循环来做这个时我得到一个错误。
因此,例如,如果列由各种因素a,b,c组成,并且我想为每个因子编写1或0的虚拟变量,那么我必须创建的代码是:
h = rep(0, nrow(data))
for (i in 1:nrow(data)) {
if (data[,1] == "a") {
h[i] = 1
} else {
h[i] = 0
}
}
cbind(data, h)
这给了我错误信息“条件有长度> 1并且只使用了第一个元素”我在这个网站的其他地方看过我说我应该尝试编写自己的函数来解决问题并避免循环,我真的不明白a)如何通过编写一个函数(至少立即)来解决这个问题b)将此作为一个函数而不是循环来实现的好处。
此外,我最终使用ifelse语句创建每个向量,然后cbind将其添加到数据框中,但我们真的很感激解释。
答案 0 :(得分:2)
将if (data[,1] == "a") {
更改为if (data[i,1] == "a") {
答案 1 :(得分:1)
Aakash指出循环中的问题是正确的。你的考试是
if (data[,1] == "a")
由于您的测试不依赖于i
,因此每次迭代都是相同的。你可以像这样修复你的循环:
h = rep(0, nrow(data))
for (i in 1:nrow(data)) {
if (data[i, 1] == "a")
h[i] = 1
} else {
h[i] = 0
}
}
我们甚至可以简化,因为h
被初始化为0,在else
的情况下不需要将它设置为0,我们可以继续前进:
for (i in 1:nrow(data)) {
if (data[i, 1] == "a")
h[i] = 1
}
}
更大幅度的改进是引入矢量化。这将加快您的代码速度,一旦掌握它,通常更容易编写。 if
只能检查单个条件,但是ifelse
是矢量化的,它将采用测试矢量,“if true”结果的矢量,“if false”结果的矢量,并将它们组合起来:
h = ifelse(data[, 1] == "a", 1, 0)
有了这个,就不需要在语句之前初始化h
,我们可以将它直接添加到数据框中:
data$h = ifelse(data[, 1] == "a", 1, 0)
在这种情况下,您的测试用例和结果非常简单,我们可以做得更好。
data[, 1] == "a" ## run this and look at the output
上面的代码只是TRUE
和FALSE
的布尔矢量。如果我们在其上运行as.numeric()
,则TRUE值将被强制为1,而FALSE值将被强制为0。所以我们可以做到
data$h = as.numeric(data[, 1] == "a")
比ifelse
更有效率。
这个操作很简单,写一个函数没有任何好处。