【CSDN 编者按】在数据科学中,往往有很多种编程语言可供选择,譬如近些年爆火的 Python、应用广泛的 R,以及 C、Java、JavaScript 还有 Julia。或许根据不同的应用场景,每种语言都各有优劣。本篇文章中,一位长期耕耘在公共卫生领域的大学教授分享了切身的使用经验,其表示:学习 Julia 是一项比坚持使用 R 更好的长期投资。
原文链接:
https://drtomasaragon.github.io/posts/2023-01-14-my-journey-from-r-to-julia/
声明:本文为 CSDN 翻译,未经允许,禁止转载。
以下为译文:
使用 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 语言是单分派。
我是 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 语言则是单分派。
## 函数1
function oddsratio(a::Int, b::Int, c::Int, d::Int)
or = (a * d) / (b * c)
return or
end
下面,我们来测试一下函数oddsratio,将如上 2x2 表中的四个整数传递进去:
oddsratio(12, 6, 2, 29)
结果为:
29.0
下面是第二个函数,接受的参数为两个比例,例如病例对照中的暴露率之比。
## 函数 2
function oddsratio(p1::Float64, p0::Float64)
or = ((p1)/(1 - p1)) / ((p0)/(1 - p0))
return or
end
下面我们来测试一下函数oddsratio,将如上 2x2 表中的两个比例传递进去:
prop1 = 12 / (12 + 2) # 病例组的暴露率
prop0 = 6 / (6 + 29) # 对照组的暴露率
oddsratio(prop1, prop0)
结果为:
28.999999999999982
最后是第三个函数,接受的参数为一个 2x2 表(矩阵):
## 函数 3
function oddsratio(x::Matrix{Int})
or = (x[1, 1] * x[2, 2]) / (x[1, 2] * x[2, 1])
return or
end
下面我们来测试一下函数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 代码。