R语言整洁编码的12大原则

好的编码风格就像正确使用标点符号一样,可以让我们写的代码更容易阅读。要知道,代码很多时候写出来,是给人看的,可能是自己,也可能是他人。

对于R语言新手,也建议大家规范编码。刚开始可能不习惯,但如果坚持练习,很快就能适应并成为你的第二天性,看着不规范的代码就难受,代码完美主义技能 get。

本文我们就来学习一下R语言整洁编码的12大原则。

命名

R语言变量的命名,应仅使用小写字母(a-z)和数字(0-9)组成,可用下划线( _ )分隔名称中的单词。如:

go 复制代码
# 提倡:
short_flights <- flights |> filter(air_time < 60)

# 避免:
SHORTFLIGHTS <- flights |> filter(air_time < 60)

原则一:根据一般经验,变量名尽量有意义,可以使用长而有描述性的名称,不应使用短的没意义的名称。但是一些特殊场合可以使用短名称,如代表循环计数的 i,大家普遍采用,使用短名称更显简洁。

原则二:如果有一系列相关变量,可以给它们一个相同的前缀,而不是相同的后缀,因为相同的前缀在开发环境中自动变量补全时具有优势。

空白

我见过新手写的R语言代码,行内无空格,行之间无空行,看着让人非常压抑。比如:

go 复制代码
flights|>filter(dest=="IAH")|>group_by(year,month,day)|>summarize(n=n(),
delay=mean(arr_delay,na.rm=TRUE))|>filter(n>10)
flights|>filter(carrier=="UA",dest%in%c("IAH","HOU"),sched_dep_time>
0900,sched_arr_time<2000)|>group_by(flight)|>summarize(delay=mean(
arr_delay,na.rm=TRUE),cancelled=sum(is.na(arr_delay)),n=n())|>filter(n>10)

相信很多人都拿到过类似的代码。留白非常重要,适时空格和空行,让代码看起来更具美感,画家作画还要留白呢,是吧?

原则三:在赋值运算符两侧加空格。

原则四:在数学运算符两侧加空格(指数运算符^除外)。

go 复制代码
# 提倡
z <- (a + b)^2 / d

# 避免
z<-( a + b ) ^ 2/d

原则五:常规函数调用时,函数名与括号之间不要有空格。总是在逗号后面紧跟一个空格,就像标准英语一样。

go 复制代码
# 提倡
mean(x, na.rm = TRUE)

# 避免
mean (x ,na.rm=TRUE)

原则六:为了代码整洁美观,可以增加必要的空格,如:

go 复制代码
flights |> 
  mutate(
    speed      = distance / air_time,
    dep_hour   = dep_time %/% 100,
    dep_minute = dep_time %%  100
  )

管道

原则七:管道操作符 |> 的前面应该始终有一个空格,并且 |> 应该位于一行的末尾。

go 复制代码
# 提倡
flights |>  
  filter(!is.na(arr_delay), !is.na(tailnum)) |> 
  count(dest)

# 避免
flights|>filter(!is.na(arr_delay), !is.na(tailnum))|>count(dest)

这样做的好处显而易见。比如可以更轻松地添加新的步骤、重新排列现有步骤、修改步骤中的元素,以及通过浏览左侧的动词就可以推测代码的要完成的功能。

原则八:管道中的函数如果有命名参数,可以将每个参数放在独立的行上。如果函数没有命名参数,可以将所有内容放在一行中,确有必要时也可以分多行。

go 复制代码
# 提倡
flights |>  
  group_by(tailnum) |> 
  summarize(
    delay = mean(arr_delay, na.rm = TRUE),
    n = n()
  )

# 避免
flights |>
  group_by(
    tailnum
  ) |> 
  summarize(delay = mean(arr_delay, na.rm = TRUE), n = n())

原则九:管道第一步之后,每行缩进两个空格。如果要将参数放在自己的行上,再缩进两个空格。确保 ) 位于自己的行上,并且与函数的第一个字符保持对齐。

go 复制代码
# 提倡
flights |>  
  group_by(tailnum) |> 
  summarize(
    delay = mean(arr_delay, na.rm = TRUE),
    n = n()
  )

# 避免
flights|>
  group_by(tailnum) |> 
  summarize(
             delay = mean(arr_delay, na.rm = TRUE), 
             n = n()
           )

# 避免
flights|>
  group_by(tailnum) |> 
  summarize(
  delay = mean(arr_delay, na.rm = TRUE), 
  n = n()
  )

如果你的管道很适合写在一行,也可以回避上述一些规则。但根据经验,短语句变长是很常见的,因此从长远来看,一开始就选择垂直书写方式是有益的,这往往会节省许多时间。

go 复制代码
# 一行看着很紧凑
df |> mutate(y = x + 1)

# 尽管这种写法占了4行,但这在未来很容易扩展到更多变量和步骤。
df |> 
  mutate(
    y = x + 1
  )

当然这并没有一定之规,我个人的话,还是倾向于第一种写法。当后续需要扩展时,再换成第二种也不迟。一开始就写第二种,稍显繁琐了。

原则十:要避免写很长的管道,比如超过10-15行。尝试将长管道分解为小的子任务。这更有助于调试,查看中间结果,并且更容易检查结果是否符合预期。

Ggplot2

原则十一:适用于管道的规则也适用于 ggplot2,只需要以对待 |> 相同的方式对待 + 即可。

go 复制代码
flights |> 
  group_by(month) |> 
  summarize(
    delay = mean(arr_delay, na.rm = TRUE)
  ) |> 
  ggplot(aes(x = month, y = delay)) +
  geom_point() + 
  geom_line()

同样,如果你无法将函数的所有行都放在一行中,请将每个参数放在自己的行上:

go 复制代码
flights |> 
  group_by(dest) |> 
  summarize(
    distance = mean(distance),
    speed = mean(distance / air_time, na.rm = TRUE)
  ) |> 
  ggplot(aes(x = distance, y = speed)) +
  geom_smooth(
    method = "loess",
    span = 0.5,
    se = FALSE, 
    color = "white", 
    linewidth = 4
  ) +
  geom_point()

分段注释

原则十二:随着脚本的长度变长,你可以使用分段注释将文件分解为可管理的部分:

go 复制代码
# Load data --------------------------------------

# Plot data --------------------------------------

小结

可以看到,遵循良好的规范写出来的代码让人赏心悦目,而糟糕代码则让人看不下去。最后,推荐一个R包:styler,它可以整理现有代码,使其符合编码规范,是拯救已有糟糕代码的神器。

  • 本文内容主要来源于《R数据科学》第二版。我们正在以该书为教材,进行R语言入门培训,课程采用录播 + 微信群答疑的形式,学员反映效果还不错。以下是学员的评价。
  • 用R把数据整理好了,上传到 Galaxy 平台,一键分析,简直完美,这是生信未来的形式。

关于简说基因

生信平台

Galaxy中国(UseGalaxy.cn)致力于打造中国人的云上生物信息基础设施。大量在线工具免费使用。无需安装,用完即走。活跃的用户社区,随时交流使用心得。
*

生信培训

简说基因的生信培训班,荣获学员的一致好评。如果你也对生物信息学感兴趣,欢迎来跟简说基因,学真生信

生信分析

我们能够承接所有 NGS 组学数据分析业务,包括但不限于 WGS / WES / RNA-seq 等。基因组组装、注释,以及各种重测序业务都可以与简说基因合作。

相关推荐
qq_537562672 分钟前
跨语言调用C++接口
开发语言·c++·算法
wjs202413 分钟前
DOM CDATA
开发语言
Tingjct14 分钟前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
猷咪41 分钟前
C++基础
开发语言·c++
IT·小灰灰42 分钟前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧44 分钟前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q44 分钟前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳044 分钟前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾1 小时前
php 对接deepseek
android·开发语言·php
2601_949868361 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter