数据科学家的编程语言选择:R到Julia的转变

发表时间: 2023-02-02 21:16

【CSDN 编者按】在数据科学中,往往有很多种编程语言可供选择,譬如近些年爆火的 Python、应用广泛的 R,以及 C、Java、JavaScript 还有 Julia。或许根据不同的应用场景,每种语言都各有优劣。本篇文章中,一位长期耕耘在公共卫生领域的大学教授分享了切身的使用经验,其表示:学习 Julia 是一项比坚持使用 R 更好的长期投资。

原文链接:
https://drtomasaragon.github.io/posts/2023-01-14-my-journey-from-r-to-julia/

声明:本文为 CSDN 翻译,未经允许,禁止转载。


作者:Tomás Aragón
译者 | 弯月 责编 | 屠敏
出品 | CSDN(ID:CSDNnews)

以下为译文:

使用 R 语言的历史


15 年以来,我一直在美国加州大学伯克利分校公共卫生学院教授“基于R语言的应用流行病学”。我从 2000 年初开始教授这门课程,当时大多数人对 R 并不感兴趣。后来,R 语言的受欢迎程度提高了,参加我的课程的人数也增加了。我教授的是应用流行病学的 R 语言编程基础。学生需要完成自己选择的项目。因为我的学生来自多个学科,因此他们的项目通常非常有创意,我从他们身上也学到了很多知识。

在过去的 15 年里,我亲眼目睹了“数据科学”的兴起,以及学生们在项目中表现出来的独特性和创造性。当然,这门课程本身也在不断发展。我利用贝叶斯网络作为统一框架来介绍概率依赖、因果图和决策网络(用于决策分析)。

后来,我开始尝试 Python。不幸的是,疫情导致我的教学中断,因为我是美国旧金山的卫生主任兼人口卫生司司长。为了应对疫情,我几乎没有时间学习 Python 以及 Python 数据分析。

我不记得具体的时间,但最终我发现了 Julia,这是一种专为科学计算而设计的编程语言,不仅拥有 Python 和 R 的简单性,而且还具备 C++ 的速度。我爱上了 Julia,并放弃了学习 Python。无论是过去还是现在,我都没有时间同时学习一门以上的编程语言。随着我对 Julia 的了解越来越多,我开始相信,对我来说,学习 Julia 是一项比坚持使用 R 更好的长期投资。

我通过编程来探索或测试我对流行病的研究、学习新方法以及可视化和分析数据。我对贝叶斯网络、决策网络、因果推理、马尔可夫决策过程,以及基于主体的建模很感兴趣。

以下是我认为流行病学家十分看重的一些 Julia 的关键特性:

  • 多重分派

  • 复合类型

  • 即时编译

  • 速度(非常快)

  • 社区

使用 Julia 编程更加简单。例如,在 R 中,我们需要尽量避免循环,因为这类语句非常低效。但在 Julia 中,循环的执行效率很高,因为 Julia 会在执行之前先编译代码。

下面,我用一个简单的例子来演示多重分派。注意,R 语言是单分派。


Julia 中的多重分派示例


我是 R 语言的 epitools 包的创建者。我开发了基本流行病学的分析函数,其中有几个来自 Kenneth J. Rothman 编写的教科书《现代流行病学》。例如,如果我想创建一个函数来计算 2x2 列联表的优势比,则可以通过以下几种方式提供数据:

  • 四个整数计数

  • 两个比例

  • 一个 2x2 表(矩阵)

  • 两个向量,带有分类数据

如果我想编写一个函数来处理这些数据类型,就不得不对数据类型进行大量处理和检查,才能调用下一个函数(嵌套或外部)。其中涉及的工作量超出了必要。下面,我们来看看如何利用 Julia 的多重分派来实现这个函数。

2003 年,我们发表了一项研究,证明饮用未经过滤的市政自来水与晚期 HIV 病患者感染隐孢子虫病有一定的关系。下面是论文中的列联表。

暴露

病例

对照

最高

12

6

中级

35

64

最低

2

29

让我们比较一下暴露最高的类别和最低的类别,计算未经调整的优势比。下面的计算使用的是 2x2 列联表。

暴露

病例

对照

最高

12

6

最低

2

29

对于结构化的表,优势比需要计算交叉积。

对于病例对照研究的设计,优势比就是暴露的比例。

我们将创建三个函数,分别接收三种不同类型的参数来计算优势比。

  • 四个整数计数

  • 两个比例

  • 一个 2x2 表(矩阵)

问题在于,这三个函数的名称相同,皆为oddsratio。在 Julia 中,我们可以利用多重分派实现。相比之下,R 语言则是单分派。

## 函数1function oddsratio(a::Int, b::Int, c::Int, d::Int)or = (a * d) / (b * c)return orend

下面,我们来测试一下函数oddsratio,将如上 2x2 表中的四个整数传递进去:

oddsratio(12, 6, 2, 29)

结果为:

29.0

下面是第二个函数,接受的参数为两个比例,例如病例对照中的暴露率之比。

## 函数 2function oddsratio(p1::Float64, p0::Float64)or = ((p1)/(1 - p1)) / ((p0)/(1 - p0))return orend

下面我们来测试一下函数oddsratio,将如上 2x2 表中的两个比例传递进去:

prop1 = 12 / (12 + 2) # 病例组的暴露率prop0 = 6 / (6 + 29) # 对照组的暴露率oddsratio(prop1, prop0)

结果为:

28.999999999999982

最后是第三个函数,接受的参数为一个 2x2 表(矩阵):

## 函数 3function oddsratio(x::Matrix{Int})or = (x[1, 1] * x[2, 2]) / (x[1, 2] * x[2, 1])return orend

下面我们来测试一下函数oddsratio,将如上的 2x2 表传递进去:

tab = [12 6; 2 29]

2×2 Matrix{Int64}:

12 6

2 29

oddsratio(tab)

结果为:

29.0

这就是多重分派。函数 oddsratio 有三种写法,可以处理多种数据类型。请注意,编写这些代码非常容易。

methods(oddsratio)

函数 oddsratio 的三种调用方法:

  • oddsratio(a::Int64, b::Int64, c::Int64, d::Int64) in Main at In[2]:2

  • oddsratio(p1::Float64, p0::Float64) in Main at In[4]:2

  • oddsratio(x::Matrix{Int64}) in Main at In[6]:2


总结


在本文中,我简单介绍了我从 R 切换到 Julia 的主要原因。我说明了如何编写多重分派函数。请注意,使用三种方法来处理不同参数类型的函数对我来说是多么容易。

我很喜欢 Julia,相信你也会喜欢。

最后,你还可以通过 Julia 运行 R 或 Python 代码。