R中的编码实践:不同风格的优缺点是什么?

Jor*_*eys 34 coding-style r vectorization

最近关于使用require与::的问题引发了关于在R中编程时使用哪种编程风格的问题,以及它们的优点/缺点.浏览源代码或在网上浏览,您会看到许多不同的样式显示.

我的代码中的主要趋势:

  • 重度矢量化我使用索引(和嵌套索引)玩了很多,这有时会产生相当模糊的代码,但通常比其他解决方案快得多.例如:x[x < 5] <- 0而不是x <- ifelse(x < 5, x, 0)

  • 我倾向于嵌套函数以避免使用我需要清理的临时对象来重载内存.特别是对于操纵大型数据集的函数,这可能是一个真正的负担.例如:y <- cbind(x,as.numeric(factor(x)))而不是y <- as.numeric(factor(x)) ; z <- cbind(x,y)

  • 我编写了很多自定义函数,即使我只在例如一次使用代码.一个sapply.我相信它可以让它更容易阅读,而不会产生可以保持躺着的物体.

  • 不惜一切代价避免循环,因为我认为矢量化更清洁(更快)

然而,我注意到对此的看法不同,有些人倾向于背弃他们所谓的"Perl"编程方式(甚至是"Lisp",所有这些括号都在我的代码中飞来飞去.我不知道虽然走得那么远.

您认为R中的良好编码实践是什么?

您的编程风格是什么,您如何看待它的优缺点?

Rei*_*son 21

我所做的将取决于我编写代码的原因.如果我正在为我的研究(日常工作)编写数据分析脚本,我想要一些有效的东西,但几个月甚至几年后都是可读和可理解的.我不太关心计算时间.矢量化lapply等.可以导致混淆,我想避免.

在这种情况下,如果lapply让我跳过箍来构造适当的匿名函数,我会使用循环来重复进程.我会ifelse()在你的第一个子弹中使用,因为至少在我看来,这个调用的意图比子集+替换版本更容易理解.通过我的数据分析,我更关心的是让事情变得正确而不是计算时间 - 当我不能在办公室工作时,总会有周末和夜晚.

对于你的其他子弹; 我倾向于内联/嵌套调用,除非它们非常微不足道.如果我明确地说明了这些步骤,我发现代码更容易阅读,因此不太可能包含错误.

我一直在编写自定义函数,特别是如果我要在循环或类似函数中重复调用函数的代码.这样我就将代码从主数据分析脚本中封装到它自己的.R文件中,这有助于保持分析的意图与分析的完成方式不同.如果该功能有用,我可以将其用于其他项目等.

如果我正在编写一个包的代码,我可能会以与我的数据分析(熟悉度)相同的态度开始,以获得我所知道的工作,然后只有在我想改进计算时间时才进行优化.

我试图避免做的一件事是,当我编码时,无论我编码什么,都太聪明了.最终,我从来没有像我想象的那样聪明,如果我保持简单,那么如果我想要聪明的话,我往往不会像往常那样经常摔倒在脸上.

  • +1太聪明了.虽然,我习惯使用索引,我可以很容易地阅读代码,看看它做了什么.但我同意,对于那个落后于我的人来说,这并不总是那么明显. (6认同)

Rom*_*rik 11

.R为各种代码块编写函数(在独立文件中),这些代码在概念上做了一件事.这使事情变得简短而甜蜜.我发现调试有点容易,因为traceback()它给你哪个函数产生了错误.

我也倾向于避免循环,除非绝对必要.如果我使用for()循环,我觉得有点脏.:)我努力做所有矢量化或应用系列.这并不总是最好的做法,特别是如果您需要向另一个不熟练应用或矢量化的人解释代码.

关于requirevs 的使用::,我倾向于使用两者.如果我只需要某个软件包中的一个函数,我就可以使用它::,但是如果我需要多个函数,我会加载整个软件包.如果包之间的函数名称存在冲突,我会尝试记住并使用::.

我试图为我想要实现的每项任务找到一个函数.我相信在我之前的某个人已经想到了它并且创造了一个比我能想到的任何东西都更好的功能.这有时是有效的,有时不是那么多.

我尝试编写代码以便能够理解它.这意味着我会进行大量评论并构建代码块,以便它们能够以某种方式遵循我想要实现的目标.我经常在函数进展时覆盖对象.我认为这保持了任务的透明度,特别是如果你稍后在函数中引用这些对象.当计算时间超过我的耐心时,我会想到速度.如果一个函数需要很长时间才能完成,我开始浏览SO,我看是否可以改进它.

我发现一个好的语法编辑器,代码折叠和语法着色(我使用Eclipse + StatET)给我带来了很多麻烦.

根据VitoshKa的帖子,我补充说我使用大写词(sensu Java)作为函数名,并使用fullstop.delimited作为变量.我看到我可以有另一种函数参数样式.

  • 同意,apply基本上是"for each elements in",这与for循环完全一样.唯一的区别是,当您习惯应用时,您不必考虑某些细节(例如按列,行,列表元素选择),并且代码可以非常易读.但也许只是我. (2认同)

Vit*_*hKa 8

命名约定对于代码的可读性非常重要.受R的S4内部风格的启发,我使用的是:

  • camelCase用于全局函数和对象(如doSomething,getXyyy,upperLimit)
  • 函数以动词开头
  • 未导出,辅助函数始终以"."开头.
  • 局部变量和函数都是小写字母和"_"语法(do_something,get_xyyy),它可以很容易地区分本地变量和全局变量,从而导致更清晰的代码.