最近关于使用require vs. ::的问题引发了关于在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中的编码实践是什么?
您的编程风格是什么,您如何看待它的优缺点?
答案 0 :(得分:20)
我所做的将取决于我编写代码的原因。如果我正在为我的研究(日常工作)编写数据分析脚本,我想要一些有效的东西,但几个月甚至几年后都是可读和可理解的。我不太关心计算时间。使用lapply
等进行矢量化。可能导致混淆,我想避免。
在这种情况下,如果lapply
让我跳过箍来构造适当的匿名函数,我会使用循环进行重复过程。我会在你的第一个项目符号中使用ifelse()
因为,至少在我看来,该调用的意图比子集+替换版本更容易理解。通过我的数据分析,我更关心的是让事情变得正确而不是计算时间 - 当我不能在办公室工作时,总会有周末和夜晚。
对于你的其他子弹;我倾向于不来内联/嵌套调用,除非它们非常简单。如果我明确地说明了这些步骤,我发现代码更容易阅读,因此不太可能包含错误。
我一直在编写自定义函数,特别是如果我要在循环或类似函数中重复调用函数的代码。这样我就将代码从主数据分析脚本中封装到它自己的.R
文件中,这有助于保持分析的意图与分析的完成方式不同。如果该功能很有用,我可以将其用于其他项目等。
如果我正在为一个软件包编写代码,我可能会以与我的数据分析(熟悉程度)相同的态度开始,以获得我所知道的工作,并且只有在我想改善计算时间时才进行优化。
我尝试避免做的一件事是,当我编码时,太聪明,无论我编码什么。最终,我从来没有像我想象的那样聪明,如果我保持简单,那么如果我想要聪明的话,我往往不会像往常那样经常摔倒在地。
答案 1 :(得分:10)
我为各种代码块编写函数(在独立的.R
文件中),这些代码在概念上做了一件事。这使事情变得简短而甜蜜。我发现调试更容易一些,因为traceback()
会给你哪个函数产生错误。
我也倾向于避免循环,除非绝对必要。如果我使用for()
循环,我觉得有点脏。 :)我努力做所有矢量化或应用系列。这并不总是最好的做法,特别是如果您需要向另一个不熟练应用或矢量化的人解释代码。
关于require
vs ::
的使用,我倾向于使用两者。如果我只需要某个包中的一个函数,我可以通过::
使用它,但是如果我需要多个函数,我会加载整个包。如果包之间的函数名称存在冲突,我会尝试记住并使用::
。
我尝试为我想要实现的每项任务找到一个函数。我相信在我之前的某个人已经想到了它并且创造了一个比我能想到的任何东西都更好的功能。这有时会起作用,有时候不会那么多。
我尝试编写代码以便能够理解它。这意味着我会进行大量评论并构建代码块,以便它们能够以某种方式遵循我想要实现的目标。我经常在函数进展时覆盖对象。我认为这保持了任务的透明度,特别是如果你稍后在函数中引用这些对象。当计算时间超过我的耐心时,我会想到速度。如果一个函数需要很长时间才能完成,我开始浏览SO,我看是否可以改进它。
我发现一个带有代码折叠和语法着色的好语法编辑器(我使用Eclipse + StatET)给我带来了很多麻烦。
基于VitoshKa的帖子,我补充说我使用大写词(sensu Java)作为函数名,并使用fullstop.delimited作为变量。我看到我可以为函数参数设置另一种样式。
答案 2 :(得分:7)
命名约定对于代码的可读性非常重要。受R的S4内部风格的启发,我使用的是:
答案 3 :(得分:4)
对于数据杂耍,我尝试使用尽可能多的SQL,至少对于GROUP BY平均值这样的基本内容。我很喜欢R,但有时候你会发现你的研究策略还不够好,无法找到隐藏在另一个包中的另一个功能。对于我的情况,SQL方言没有太大差异,代码非常透明。大多数情况下,阈值(何时开始使用R语法)相当直观。 e.g。
require(RMySQL)
# selection of variables alongside conditions in SQL is really transparent
# even if conditional variables are not part of the selection
statement = "SELECT id,v1,v2,v3,v4,v5 FROM mytable
WHERE this=5
AND that != 6"
mydf <- dbGetQuery(con,statement)
# some simple things get really tricky (at least in MySQL), but simple in R
# standard deviation of table rows
dframe$rowsd <- sd(t(dframe))
所以我认为这是一个很好的做法,并且建议在大多数用例中使用SQL数据库作为数据。我也在研究TSdbi并在关系数据库中保存时间序列,但还不能真正判断它。