R中的For循环是邪恶的吗?

use*_*331 3 loops for-loop structure r

我听说你并不打算将程序编程风格强加到R.我发现这很难.我刚刚用for循环解决了一个问题.这是错的吗?有更好的,更"R风格"的解决方案吗?

问题:我有两列:Col1和Col2.Col1包含以自由格式输入的职务.我想使用Col2将这些职位分类收集到类别中(因此"初级技师","工程技师"和"机械技术"都被列为"技师".

我这样做了:

jobcategories<-list(
"Junior Technician|Engineering technician|Mech. tech." = "Technician",
"Manager|Senior Manager|Group manager|Pain in the ****" = "Manager",
"Admin|Administrator|Group secretary" = "Administrator")

for (currentjob in names(jobcategories)) {
  df$Col2[grep(currentjob,data$Col1)] <- jobcategories[[currentjob]]
}
Run Code Online (Sandbox Code Playgroud)

这会产生正确的结果,但我不能动摇(因为我的程序经验)我没有正确使用R的感觉.R专家可以让我摆脱困境吗?

编辑

我被问到原始数据.不幸的是,我无法提供它,因为它有机密信息.它基本上是两列.第一列仅包含400多行不同的职位(以及奇怪的个人姓名).大约有20种不同的类别可以分成这400种标题.第二列以NA开始,然后在运行for循环后填充.

jos*_*ber 7

你是对的,在R中经常不鼓励for循环,根据我的经验,这有两个主要原因:

成长对象

如在R inferno的第2圈中雄辩地描述的那样,一次一个元素生长一个元素可能是非常低效的,这通常是for循环的诱惑.例如,这是一个非常常见但效率低下的工作流程,因为它重新分配output了循环的每次迭代:

output <- c()
for (idx in indices) {
  scalar <- compute.new.scalar(idx)
  output <- c(output, scalar)
}
Run Code Online (Sandbox Code Playgroud)

可以通过预分配output到适当的大小并使用for循环或使用类似的函数来消除这种低效率sapply.

错过更快的矢量化替代品

低效率的第二个来源是当存在矢量化替代时,在快速操作上执行for循环.例如,请考虑以下代码:

s <- 0
for (elt in x) {
  s <- s + elt
}
Run Code Online (Sandbox Code Playgroud)

这是一个非常快速的操作的for循环(添加两个数字),并且与向量化sum函数相比,循环的开销将是显着的,向量函数将向量中的所有元素相加.该sum函数很快,因为它是用C实现的,所以它s <- sum(x)比使用for循环更有效(更不用说减少输入了).有时需要更多的创造力来弄清楚如何用带有矢量化替代品的快速内部替换for循环(cumsum并且diff出现很多),但它可以显着提高效率.如果你有一个快速循环内部但无法弄清楚如何使用矢量化函数来实现同样的事情,我发现用Rcpp包重新实现循环可以产生更快的替代方案.

综上所述...

如果你不正确地增长对象或者你有一个非常快的内部循环并且整个事物可以用矢量化操作替换,那么循环可能会很慢.否则你可能不会失去太多效率,因为apply系列函数也在内部执行循环.


Jac*_*ley 2

for循环在 R 中并不是“邪恶的”,但与基于向量的方法相比,它们通常很慢,并且通常不是最佳的可用解决方案,但是它们很容易实现且易于理解,您不应该低估其中任何一个的价值。

因此,在我看来,for如果您需要快速完成某件事并且找不到更好的方法,并且不需要太担心速度,则应该使用循环。

  • 我不同意你关于“慢”的部分。通常,慢的不是循环,而是人们在循环中执行内存效率操作(即“append()”)。for 循环可能比“sapply()”“替代方案”更快。但这就是说,使用 for 循环是“错误的”,因此当“sum()”存在时,将向量中的项目相加。尽可能使用向量化运算是一个很好的一般规则。 (3认同)