Python并非数据科学领域的理想语言(第一部分):亲身经历
是的,我准备好触碰烫手山芋了。语言之争,就此展开。
其实我想首先强调的是:使用你熟悉的工具。若是Python,很好,就用它。同时,选择最适合任务的工具。若是Python,很好,就用它。更何况,仅因你已用它处理各种任务而顺手拿来完成单一任务也无可厚非。整天用锤子钉钉子的人,用锤子开啤酒瓶或挠背也情有可原。同理,整天用 Python 编程的人,用它来拟合混合线性模型也无可厚非。若对你有效,那太好!继续保持。但若你感到吃力,若事情比应有的难度更高,这系列文章或许正适合你。
我认为人们过度推崇Python作为数据科学的“唯一语言”。它存在诸多值得注意的局限性。许多数据科学任务,我更倾向于用R而非Python完成。1 我认为Python在数据科学领域普及的根源在于历史偶然性,加上它在多数场景下勉强可用——而非其天生适合数据科学工作。
与此同时,我认为Python在深度学习领域表现相当出色。2 PyTorch成为行业标准自有其道理。此处提及数据科学时,我特意将深度学习排除在外。我指的是其他所有领域:数据处理、探索性数据分析、可视化、统计建模等。正如开篇所述,我理解若你因正当理由(如训练AI模型)已全天使用Python工作,可能也希望用Python完成其余任务。我在教授深度学习课程时就是这么做的。但这并不意味着我不会对Python世界中数据科学操作的繁琐感到沮丧。
来自前线的观察
让我们从我的亲身经历开始,暂不探讨其成因。二十多年来,我一直运营着一个计算生物学研究实验室。期间与约三十名研究生和博士后共事,他们都是能力出众的计算科学家。实验室政策允许所有人自由选择编程语言和工具,我从不干涉具体选择。而绝大多数人最终都选择了Python作为首选语言。
以下是我与Python用户常见的典型互动场景:学生来办公室展示成果时,我会说“这很好,但能否快速用另一种方式绘制数据?”或“能否计算我刚设定的这个量,看看绘制后效果如何?”之类的要求。通常我提出的要求,都是我知道用R语言几分钟就能完成的事。例如:将箱线图转换为小提琴图或反之;将折线图转为热力图;用密度估计图替代直方图;对排序数据值而非原始数据值进行计算等等。而使用Python的学生们毫无例外都会回答:”这需要我花点时间。“让我回座位研究下再回来。”必须强调:这些都是优秀学生。问题不在于他们不懂工具,而在于工具本身存在缺陷。这些工具似乎过于繁琐或令人困惑,导致我认为理应简单的请求往往变得复杂。3
无论这种体验的成因如何,我不得不得出结论:Python的数据分析方式存在根本性缺陷。这可能是语言本身的缺陷,也可能是现有软件库的局限,或是两者的结合,但无论如何,其影响是真实存在的,我经常能看到这种现象。事实上,我还有另一个例子,以防你试图反驳说:“这是技能问题,找更优秀的学生就行了。” 去年秋天,我与一位经验丰富的数据科学家合开生物学人工智能模型课程。这位专家所有工作都基于Python,对NumPy、pandas和matplotlib了如指掌。课堂上我负责理论讲解,他负责指导Python实操练习。因此我有幸观察这位Python专家处理各类实例的过程。而我面对这些代码示例时,常常不禁感叹:“为什么非要搞得这么复杂?”许多情况下,明明用几行简单的R代码就能实现的功能,最终却变成了冗长且相当迂回的代码。若没有深入钻研并彻底重塑编程思维模式,我绝对写不出这样的代码。这种陌生感并非“哇,如此陌生却又如此优雅”的惊叹,而是“哇,这太陌生、太怪异、太笨拙了”的诧异。需要重申的是,我认为这并非源于同事能力不足——他极其出色。问题似乎根植于工具本身的架构设计。
关于数据科学优秀语言的几点思考
请允许我稍作退步,梳理选择数据科学语言的基本考量。所谓数据科学,指的是剖析数据、提炼规律、拟合模型及可视化呈现。简言之,这正是科学家及其他研究人员4分析数据时开展的工作。这种活动与数据工程或应用开发截然不同——即便该应用涉及大量数据处理任务。
我在此定义的数据科学包含大量交互式数据探索以及快速的一次性分析或实验。因此,任何适用于数据科学的语言都必须是解释型语言,能在交互式终端或笔记本格式中使用。这也意味着性能考量次之。当你需要对正在处理的数据进行快速线性回归时,根本不在乎任务耗时50毫秒还是500毫秒。真正重要的是能否直接打开终端,输入几行代码,在一两分钟内获得结果——而非耗费时间创建新项目、编写冗余代码取悦编译器,最终发现编译耗时甚至超过运行本身。
若承认交互式工作与低启动成本是数据科学语言的关键特性,那么Python这类脚本语言,或R/Matlab/Mathematica等数据科学专用语言便成为不二之选。Julia也是候选者,但坦白说我对其了解有限,无法展开论述——或许它正是最理想的数据科学语言。但值得注意的是,部分深度使用者对此存疑。无论如何,本文不再深入探讨。此外,我将排除Matlab、Mathematica这类专有语言,以及生态系统匮乏的冷门语言(如Octave)。由此可见,R和Python才是现实可选方案。5
继续探讨前,容我补充几点关于性能的思考。性能通常需要与语言的其他特性权衡取舍。简而言之,性能提升要么以增加程序员额外负担为代价(如Rust),要么以增加隐蔽错误风险为代价(如C语言),或两者兼而有之。对于数据科学应用,我认为隐蔽错误或错误结果的高风险不可接受,且程序员的便利性比纯粹性能更重要。计算机运行迅捷,而思考耗费心力。我宁愿减少向计算机传达指令的脑力消耗,也愿多等待片刻获取结果。因此语言越能简化我的工作,就越理想。若某项分析确实受性能限制,待我完全掌握具体操作与所需计算后,随时可将该部分重写为Rust代码。
逻辑与后勤的分离
避免让工作变得比必要更复杂的关键在于,将分析逻辑与执行细节分离。我的意思是:我希望能在概念层面明确数据分析方式及计算结果,而不必纠结于具体执行细节。通常而言,若我需要考虑数据类型、数值索引或循环结构,或不得不手动拆解重组数据集,很可能就陷入了技术细节的泥潭。6
具体而言,以帕尔默群岛企鹅数据集为例。该数据包含三种企鹅物种,分别栖息于三座不同岛屿。假设我需要计算每种企鹅物种与岛屿组合的平均体重及标准差,且需排除体重未知的情况。理想的数据科学语言应能用类似以下表达实现该计算,且所需代码量约等于撰写本句所需的英文长度。事实上,R语言和Python均能实现此目标。
以下是采用tidyverse方法的R语言相关代码:
library(tidyverse)
library(palmerpenguins)
penguins |>
filter(!is.na(body_mass_g)) |>
group_by(species, island) |>
summarize(
body_weight_mean = mean(body_mass_g),
body_weight_sd = sd(body_mass_g)
)
以下是使用pandas包的等效Python代码:
import pandas as pd
from palmerpenguins import load_penguins
penguins = load_penguins()
(penguins
.dropna(subset=['body_mass_g'])
.groupby(['species', 'island'])
.agg(
body_weight_mean=('body_mass_g', 'mean'),
body_weight_sd=('body_mass_g', 'std')
)
.reset_index()
)
这两个示例高度相似。在如此复杂度的分析中,Python表现良好。我认为R代码稍易阅读(注意Python代码中大量引号和括号的使用),但差异微乎其微。两种方案均采用企鹅数据集,剔除体重缺失的企鹅记录,指定按企鹅物种与岛屿的每种组合分别进行计算,最后求取均值与标准差。
对比之下,等效的R语言代码充斥着繁琐逻辑操作,而我仅使用Python基础语言特性且未借助任何数据处理包:
from palmerpenguins import load_penguins
import math
penguins = load_penguins()
# Convert DataFrame to list of dictionaries
penguins_list = penguins.to_dict('records')
# Filter out rows where body_mass_g is missing
filtered = [row for row in penguins_list if not math.isnan(row['body_mass_g'])]
# Group by species and island
groups = {}
for row in filtered:
key = (row['species'], row['island'])
if key not in groups:
groups[key] = []
groups[key].append(row['body_mass_g'])
# Calculate mean and standard deviation for each group
results = []
for (species, island), values in groups.items():
n = len(values)
# Calculate mean
mean = sum(values) / n
# Calculate standard deviation
variance = sum((x - mean) ** 2 for x in values) / (n - 1)
std_dev = math.sqrt(variance)
results.append({
'species': species,
'island': island,
'body_weight_mean': mean,
'body_weight_sd': std_dev
})
# Sort results to match order used by pandas
results.sort(key=lambda x: (x['species'], x['island']))
# Print results
for result in results:
print(f"{result['species']:10} {result['island']:10} "
f"Mean: {result['body_weight_mean']:7.2f} g, "
f"SD: {result['body_weight_sd']:6.2f} g")
该代码篇幅冗长,包含大量循环,且需显式拆解数据集再重新组合。无论选择何种语言,相信您都能看出:摆脱数据处理琐事的版本远优于深陷后勤细节的版本。7
本文暂告段落,篇幅已足够。后续文章将探讨Python相较于R语言在数据分析中更复杂的具体问题。简言之,我认为Python代码常陷入数据后勤处理困境有以下原因:即便程序员竭力规避后勤工作,专注于高层次概念化编程模式,但语言特性或现有库往往会阻碍这些努力。具体细节将在后续文章中详述,敬请期待。
1 就数据科学领域常用的语言而言,我只熟悉R和Python,因此本文将重点比较这两种语言。或许您熟悉的其他语言能完美解决我提出的所有问题——可能是Julia、Ruby或Haskell。很好,若您喜欢就用它吧。
2 至少在当今深度学习的实践方式中是如此。在我看来,PyTorch(或TensorFlow)代码要求我们显式操作张量、思考维度问题以及数据存储位置的事实,暗示着我们尚未找到某种抽象层级。而在其他数据分析任务中,我们早已无需处理这些繁琐操作。
3 我列举的绘图示例对使用plotnine的学生而言不成问题——我正鼓励实验室全体成员采用该工具。但对于使用matplotlib或seaborn的学生(这两者在Python社区似乎更为常见),我从未见过有人能即兴对图表进行实质性修改。
4 我之所以在“科学家”之外添加“研究者”,是因为经济学家或记者等群体也常从事数据科学工作,而我们通常不会将这两类人称为科学家。“研究者”作为更宽泛的术语,适用于任何从事研究工作的人员,无论其研究领域是否属于科学范畴。
5 曾几何时有过Perl语言,所幸众人皆认同它并非优秀语言。Python的成功很大程度上源于它在Perl擅长的多数领域都表现更优。
6 这正是我在脚注2中提及的对当前深度学习代码的主要批评。所有工作都沦为后勤事务。何处有深度学习框架能抽象掉所有后勤工作,让我仅需表达信息流经网络的逻辑?
7 仅用基础R功能实现相同实验简直像作弊。我们只需一次函数调用就能完成全部操作:
aggregate(body_mass_g ~ species + island, penguins, (x) c(mean = mean(x), sd = sd(x))) 这个例子彰显了R在数据分析领域的强大能力。它同时也揭示了基础R社区对tidyverse的主要批评之一:tidyverse过于冗长,不过是重新发明了R诞生以来就存在的概念。
本文文字及图片出自 Python is not a great language for data science. Part 1: The experience

> 例如将箱线图转换为小提琴图或反之,将折线图转换为热力图,绘制密度估计图而非直方图,对排序数据值而非原始数据值进行计算等等。
这些大多与Python无关,而是matplotlib的问题。若想在Python中获得ggplot那种设计精妙的体验,请使用plotnine
> 我认为R代码更易于阅读(注意Python代码需要多少引号和括号)
这与Python无关,而是tidyverse的问题。R能使用更简洁语法的原因在于其非标准评估机制,允许包扩展语法——这是Python未开放的功能:http://adv-r.had.co.nz/Computing-on-the-language.html
“能在R中使用这种简化语法,是因为其非标准评估机制…”
所以本质上还是Python与R的对比。
不过这种非标准评估机制虽在命令行交互时很便利,但用于编写复杂分析代码时我认为意义不大。在这种场景下,我反而认为这是R的缺陷——你不得不绕弯子才能让非标准评估处理简单操作。
R包中日益泛滥的非标准评估正是我工作转向Python的主要原因。光是让某个参数在函数中生效,就得经历繁琐的仪式和不断变动的API,简直令人抓狂。
>> 我认为R代码稍易阅读(注意Python代码需要多少引号和括号)
天啊别这样,有人会写成R那种带尾部管道符的风格吗?开头用Elixir风格的管道运算符才是正道。
若真想通过混淆参数/函数/变量来“提升”可读性(只为省略引号),Python完全能做到——只需用包装对象配合getattr技巧,就能实现
my_magic_strings.foo→‘foo’的转换。至于括号…好吧这确实是合理改进,但同样与语言无关,属于函数签名的库API设计范畴。据我所知,将管道运算符
|>置于行尾可防止表达式过早终止。否则换行符会导致其终止。为开头的管道符点赞
好奇R语言中“无库实现的后勤处理”最后一个示例会是何种景象。根据我处理“底层R代码”的经验,那绝对是场真正的噩梦。
在R中,有现成库和方案的事物往往简单,但当这些不存在时,事情就变得极其困难。通常的做法是:如果库方案无法轻松实现,那这事就干脆不做。
Python:简单的事简单,困难的事困难。
R:简单的事困难,困难的事简单。
按你描述的情况,能否说R在不知不觉中实现了AI优先?
或者seaborn库。它正是为此而生:在提供丰富功能的同时,抽象化了matplotlib中那些恼人的细节问题。
https://seaborn.pydata.org/tutorial/introduction.html
重点不在Python本身,而在于R能实现Python无法做到的事?
没有预装工具的Python一文不值。
Python本身就是预装工具。
Go语言的设计与成功有力证明:语言与其工具包生态系统不可分割。
Python的成功在于它在很多场景下都不需要更广泛的生态系统。
当然现在他们正在放弃这个理念。
我真心认为这只是巧合。Perl和Ruby存在其他缺陷,Python之所以胜出,恰恰是因为它拥有糟糕的包管理和臃肿的标准库——而非依赖这些特性。
臃肿的标准库是我忍受包管理噩梦仍坚持使用Python的唯一理由。我能不依赖任何库完成多数工作,或仅依赖像matplotlib这样反复使用的单一库。
倘若Python原本精简却需依赖包才能实现实用功能,同时仍存在包管理噩梦,它根本无法使用。
确实如此,但我同样认为,若当时解决打包噩梦更为紧迫,各方投入的精力也会多得多。
关键在于Ruby占据了网络市场,Python则统治了其他领域——而我深知,横跨多领域的技术远比单一领域更具永恒价值。
Ruby曾在网络市场与众多竞争者角逐,最终败给了Python等语言。部分原因在于Python拥有更庞大的生态系统,PHP通过WordPress等平台获得广泛应用,而JavaScript则正从浏览器领域不断扩张。
正是由于标准库的臃肿特性,才使得单个.py文件能被直接发送给他人并即时执行。
大多数Python用户既不了解也不需要venv、uv、pip等工具。
电池组是用什么语言编写的?
主要用C/C++
如今大量采用Rust语言。
如今依然大量使用Fortran,只是在上面撒了些Rust调味。(:
自Fortran 2003甚至Fortran 95版本起,其使用体验已相当出色。
更底层还有 FORTRAN 🙂
Python圈的人总爱说这话——简直像按字数拿报酬似的。这和 Perl、Ruby、Java 或 C#(DotNet)有什么区别?依我经验并无二致,只不过那些社区的人不怎么重复这句话罢了。
讽刺之处在于:我们讨论的是数据科学。98%的Python数据科学项目起步时,都要创建虚拟环境并安装Pandas和NumPy——而这些库在基础库之外还依赖着无数(真的:数以亿计)的外部依赖项。
若我完全错误请指正:默认情况下(即预编译轮子),numpy依赖为0,pandas依赖5个(其中之一正是numpy)。所以“数以亿计”的依赖说法并不准确。
pandas==2.3.3
├── numpy [所需版本: >=1.22.4, 已安装: 2.2.6]
├── python-dateutil [要求:≥2.8.2,已安装:2.9.0.post0]
│ └── six [要求:≥1.5,已安装:1.17.0]
├── pytz [要求:≥2020.1,已安装:2025.2]
└── tzdata [要求版本:≥2022.7,已安装版本:2025.2]
我不清楚_squillions_的情况,但numpy绝对有_requirements_,即使在python图中未明确标注。
例如:
这些依赖未被显示,因为它们属于构建时依赖。大多数用户执行 pip install numpy 或类似操作时,仅获取预编译二进制文件,这些依赖均不会被安装。即使自行编译,运行 numpy 时也无需这些依赖。
请参阅https://numpy.org/devdocs/building/blas_lapack.html。
若系统未安装更优实现,NumPy 必然 会回退到内部实现的极其低效的BLAS/LAPACK。但既然你使用NumPy是为了性能而非单纯为Python添加数组编程功能,自然需要更高效的实现——而这很大程度上取决于你的计算设备。
不过这并非Python特有的问题。任何科学计算领域都面临这个难题。若您坚持使用动态解释型语言(探索性交互分析可能需要如此),同时又需处理大规模数据集,就必须借助原生FFI并链接原生库。得益于标准化,您将拥有多种选择,而具体哪种最快则高度取决于硬件配置。
> 这无关Python本身,而是tidyverse生态的问题。
> 其非标准评估机制允许扩展语法的方式是Python无法实现的
这恰恰是Python与R的根本差异。
关键在于:R的语法扩展能力通常会导致混乱,但在tidyverse中正确有效地运用时,反而能提升编写和阅读代码的体验。
R更偏向统计软件而非编程语言。所以如果你是所谓的“统计学家”,R会让你倍感亲切
不,R是严肃的通用编程语言,能构建几乎任何类型的复杂科学软件。Bioconductor这类项目就是明证。
并非如此。即便是成熟的软件包也存在因R语言特性导致的缺陷。尽管如此我依然喜欢它。
能否举些例子?
或许可以与Python进行对比?
根据我的有限经验,使用R的感觉就像在浏览器中使用JavaScript:它是一个高度专注于高级、功能丰富的对象(如数据框和专用绘图对象)的平台,但你也可以用它构建几乎任何东西。
我认为这很大程度上归结于一个问题:为什么表格不能成为编程语言中的第一类公民?
若退一步思考,主流编程语言中竟没有将表格视为第一类公民的设计,这着实有些奇怪。相反,我们被迫学习多种API(如polars、pandas),这些API本质上是为表格设计的编程语言。
R语言或许最为接近,因为它将data.frame作为“第一类公民”,但多数人似乎并未采用这种设计,反而更倾向于使用dplyr中的tibbles等方案。
根本原因似乎在于我们尚未找到操纵表格数据的最佳语言(即表达方式)。某些通用理念似乎已趋于共识——Polars与dplyr颇为相似,但除SQL外仍无统一标准。
顺带一提,我认同Python表现欠佳,但同样认为R也存在不足。不过我不赞同文中具体比较的结论。
我认为主流编程语言存在若干结构缺失。表格结构是其一,矩阵是其二。图结构及其相关的状态机因语言层面的支持不足而严重被低估。最后虽非严格意义上的结构,但我认为任何内置正则引擎的语言都应配备完整的PEG解析引擎——绝大多数正则表达式灾难的根源,恰恰在于“内置正则引擎”的简单设计。
语言默认提供的工具,决定了其优雅的路径,进而塑造了整个语言的体验。我们已普遍接受的范例是键值存储——如今它们已成为标准库的必备功能。回溯90年代,当时最流行的语言 至多 将键值存储视为二等公民,其地位更接近导入对象而非数组这类基础结构。当然,任何语言都能实现哈希映射,或导入他人实现,但开发者往往会陷入噩梦般的同步数组困境——只因后者作为内置功能触手可及。
当某种特性缺乏明确的规范实现方式时,将其加入编程语言(或标准库)便充满风险。人们往往在为时已晚时才意识到选择错误,继而添加第二个版本,接着是第三个版本,如此循环往复,最终造就一个布满新手陷阱的混乱语言。
图结构就是典型例子,它包含大量相关结构。例如:边是无向、有向还是更复杂的类型?节点/边是否需要标识符和/或标签?所有节点/边是否同类,还是存在多种类型?是否允许相同节点间存在重复边?这取决于节点/边的类型,还是标签?
> 我认为任何具备正则表达式引擎的“开箱即用”语言,都应配备完整的PEG解析引擎
那样只会催生更多PEG恐怖故事。况且正则处理中的字符串与索引是通用的,而解析器本质上更像框架,复杂度远超前者,注定与多数应用场景不匹配。
我不同意。多数程序员整个职业生涯都无需使用矩阵数据结构。他们当然会用到基于矩阵的库,但绝不会直接操作矩阵。现代编程语言中矩阵未被单独定义为数据类型,这种现状完全合理。
除非你认为“大多数程序员”等同于“低劣的网页应用开发者”,否则我强烈反对。矩阵是统计学、数据分析、图形学、电子游戏、科学计算、仿真、人工智能等众多领域中至关重要的核心组件。
而这些领域的程序员要么使用专业语言(例如当他们想把程序改造成烂网页应用时就会遇到问题),要么在语法上犯下罪行,比如:
rotation_matrix.matmul(vectorized_cat)
这种说法过于激进。撇开网页应用不谈,你甚至可以完全不懂矩阵是什么就能做游戏开发。
在多数原生应用、嵌入式系统及操作系统内核开发中,这类构造根本无需存在。
我在嵌入式领域工作。曾为优化嵌入式算法权重而采用线性回归,因此需要矩阵。
若从事机器人领域,遇到矩阵的概率极高。
这正是我的观点。即便在高度专业化的证券定价库中,使用矩阵的代码量也少得惊人。
我不明白为何多数工程师要迁就你的小众需求。既然是编程语言,若缺少所需库,你大可自行开发。没人阻拦你。
此外,大量第三方项目已被纳入Python标准库。
在众多动态语言中,有不少将表格/数据框作为真正的一流数据类型:最著名的或许是Q[0]。此外还有新兴语言如Rye[1]或我自己的Lil[2]。
我推测随着时间推移,主流语言终将全面接纳表格化编程——正如它们逐步吸收了传统函数式编程中的各类语法特性(如集合操作中的map/filter/reduce)那样。
[0] https://en.wikipedia.org/wiki/Q_(programming_language_from_K…
[1] https://ryelang.org/blog/posts/comparing_tables_to_python/
[2] http://beyondloom.com/tools/trylil.html
Nushell是另一种内置表格功能的语言:
https://www.nushell.sh/book/working_with_tables.html
有趣的是Numshell、Rye和Lil之间存在诸多相似之处,尽管我认为它们源自不同的设计理念。或许这正是当下时代精神——人们追求轻量、高阶且交互式的解决方案。
另一篇关于Rye表格的文章:https://ryelang.org/cookbook/working-with/tables/
这个观察很有意思。主流语言缺乏强大的表级操作支持,可能源于现实中表规模的巨大差异——每当行数规模跃升一个数量级,就会伴随相互排斥的子问题。
处理百万行表与十亿行表时面临的问题截然不同,而十亿行表在千亿行表的挑战面前不过是微不足道的误差。标准库必须以某种方式优雅地支持这些巨大差异,这绝非易于设计的API接口。
> R或许最接近理想状态,因其将data.frame作为“第一类公民”,但多数人似乎并未采用,反而倾向使用dplyr中的tibbles等替代方案。
R语言用户普遍使用data.frame,因为tibble(及data.table)继承自data.frame。这意味着基础R函数可直接操作tibble/data.table,且三者间转换极为便捷。
每份Microsoft Excel都包含基于M语言的Power Query,其数据类型即为表格。程序本质上是对表格列与行的转换操作。虽不确定是否主流,但该功能广泛可用。M语言也集成于PowerBI和Power Automate等工具中。
> R语言或许最为接近,因其将data.frame作为“第一类公民”,但多数人似乎更倾向使用dplyr包中的tibbles等替代方案。
你忽略了R语言的data.table包https://cran.r-project.org/web/packages/data.table/vignettes…,
它非常出色。Tibbles之所以胜出,主要是因为他们在文档/入门引导方面做得更好,最终获得了业界的认可。
可读性方面,data.table功能强大,但其操作语法(无论是阅读还是编写)远不如dplyr直观。
不过通过https://dtplyr.tidyverse.org/,你可以兼得两者优势——既能享受data.table的性能提升,又能使用dplyr的语法。
没错,data.table堪称真正高吞吐量“实时”数据分析领域的顶尖工具/包。若你正在学习基础知识,或需要编写让经验较少的同事能轻松复核的代码,dplyr则非常出色。但根据我的经验,若你接触过银行、贷款机构、保险公司等一线工作者——他们每天要手动运行数百次交叉表/相关性分析——你会发现大量数据表用户。
关于作者的观点,Python在这类场景下表现相当糟糕。Pandas性能堪忧。Polars、duckdb、dask等工具或许适合生产级数据管道,但快速迭代时过于冗长且挑剔。若有人拿枪逼着我从海量平面文件中挖掘洞见,我定会要求使用搭载256GB+内存的虚拟机运行RStudio云实例+data.table。
> 为何表格不能成为编程语言的一等公民?
在q/kdb中它们就是,体验绝佳。SQL表达式同样享有第一类公民地位,让编写代码变得无比愉悦
PyTorch最初仅是Torch,且基于Lua语言。当时我并未密切关注其发展,但显然因用户需求旺盛,它被重构为Python版本,于是PyTorch应运而生。
现有多款数据导向的无代码/可视化/拖放工具,其中数据表/数据框被赋予核心地位(如Easy Data Transform、Alteryx、Knime)。
我认为这并非核心问题。在R和Julia中,表格功能强大且属于库类。关键在于这些语言具有高度表达力和可塑性。
简而言之,R深受Scheme启发,并叠加了惰性求值机制。Julia则是对Dylan开创的设计空间的另一次探索。
R是S的克隆版
> 为何表格不能成为编程语言的一等公民?
因为它们诞生于需求出现之前,甚至可能早于需求本身。
在Python中操作数组和矩阵略显笨拙,因为它并非为科学计算而设计,相关功能都是后期添加的库。而在Matlab等科学计算语言中,这类操作则高度集成且自然流畅。但反之亦然:正因MATLAB未设计实现Python的功能,其在科学计算之外的场景使用起来反而更笨拙。
人们在R语言中也使用data.table(这是我最喜欢的工具,不过已有几年没用了)。相比dplyr,data.table在操作表格数据的语言表达上形成鲜明对比。
我知道Lua的主要数据结构称为表,但我对其了解有限,不确定它们是否符合数据科学领域对表格的预期。
Lua的表本质上是关联数组。虽然还有更多特性,但它与pandas等系统使用的表格/数据框并不相同。不过你可以在Lua表的基础上构建此类框架。
https://www.lua.org/pil/2.5.html
据我所知这些本质上是哈希表,在许多语言中早已是第一类公民
说得对,你需要的语言是SQL。近年来duckdb能获得如此关注是有原因的。我认为数据科学家们忽视了SQL和Excel这类工具。
在现有方案中我完全赞同——我还为此写过博客!https://www.robinlinacre.com/recommend_sql/
但另一方面,这并不意味着SQL是理想选择——远非如此。在Python中使用DuckDB时,为追求代码简洁性、可复用性和可维护性,我常陷入编写生成SQL字符串的Python函数的模式。
这恰恰揭示了SQL的缺陷:作为语言它基本不具备组合性(相较于具备一等抽象能力的通用语言)。DuckDB语法虽略有改进,但我认为这本质上是SQL的局限。我的意思是,总觉得应该存在更优解。
SQL不仅涉及单张表,更涵盖多张表及其关联关系。若仅需对单表执行查询,基本排序、筛选、聚合和注释功能在任何语言中都易于实现。
一旦涉及连接操作,复杂度便急剧上升。理论上可通过ORM接口实现多数功能,但若仅依赖运算符,很快就会陷入运算符重载(滥用)或创建新语言的困境——后者需重新定义运算符语义:
其中*表示外连接,|表示过滤。一旦添加排序运算符、分组等功能,本质上就成了带额外步骤的SQL。
但若能内置这些功能,与数据库交互将更具原生性。
每当看到这类设计(比如谷歌新推出的带管道符的类SQL语言),我都感到困惑。在我看来SQL本身就极具可读性,语法流畅优美。
顺带一提,Python同样具备这种特性,所以这并非我偏爱Perl之类的语言。
完全同意。问题在于它们本质上是两种语言。在Python文件中,SQL只是字符串——没有语法高亮,没有编译时检查等等。若能诞生一种融合自身语言与SQL作为头等公民概念的“奎萨茨·哈德拉克”式语言固然理想,但现实是SQL差异实在太大。
首先,SQL本身并不适合动态构建。但我们常常需要动态生成查询(例如客户对产品列表应用了多个筛选条件)。SQL的处理方式要么是编写包含上千个if/else的通用查询,要么依赖存储过程——这会让代码从“行云流水”变成“天啊这是谁写的?” 或者,你也可以直接在擅长字符串拼接的语言(如Python)中实现。将整个过程封装为函数和对象后,便形成了ORM。
至今我尚未见过任何将类似SQL特性融入语言的设计,能实现基础的ORM功能。
R语言最出色,因为它自1974年诞生起就是统计分析语言(专为分析建模而设计开发)。此外tidyverse套件堪称绝妙,极大提升了数据整理与增强的效率。还有无可争议的最佳可视化系统ggplot,以及barplot()、plot()等内置函数。
但数据分析终将超越Python和R,迈向Stan和PyMC3等概率编程语言的领域。因为我们需要处理嵌套积分,而这些软件生态系统(及其他概率编程语言)提供了最佳解决方案。它们让我们能够理解复杂情境,做出优质决策。
这正是我对SAS最大的不满——所有内容要么是表格要么是文本。
多数过程同时将表格作为输入和输出,还得祈祷表格列名完全匹配。
需要循环?要么依赖表格行隐式循环,要么通过系统调用逐行处理,要么就得编写宏(全是文本)。
深有同感。我真心渴望某种数据框架,能提供编译时类型系统供LSP/IDE识别。Kusto查询语言(Azure数据探索器)实现了这一点,其自动补全和错误检查功能极其实用。可惜Kusto查询语言仅限于单一云产品。
Fortran不仅满足这些需求,还提供更强大的功能——它具备一流的多维数组支持,包括矩阵运算。
因为异构N维数据存在分布差异时,根本不存在通用的最优数据结构?虽然技术上可行,但资源消耗会比基础方案高出一个数量级。
APL语言很棒
处理表格分析的完美方案。据传pandas发明者Wes McKinney也受其启发。
我对APL的顾虑在于:1) 处理日常事务时语法不够惊艳;2) 唯一可用于生产环境的版本全是商业软件。我不会为开发项目支付开发许可费和分发版税。
深表赞同。我曾用它(GNU APL)为数据科学项目做数据预处理。经历陡峭的学习曲线后,它简直像在编写数学公式——既有趣又简洁,我非常喜欢。但它在当今数据科学领域完全无人问津。分享成果几乎不可能。不过若只是个人使用,我可能会再尝试一次。
表不就是结构体数组吗?
并非不能用这种方式建模数据(或用数组结构体建模),问题在于用户体验会变得糟糕。你可能需要超过内存容量的数据集,或需要透明支持文件系统、内存或显存的数据存储。你可能需要高效索引和查询数据。可能需要动态连接并投影其他结构体数组。可能需要检测错误数据结构的乘法操作。可能需要卓越的反射支持。这些功能在现有语言中当然可实现——毕竟它们本就存在于这些语言中——但若能更简便地实现,并获得更核心的地位就再好不过了。
其实可以设计成数组的结构体。
抛开吹毛求疵不谈,若能有个精简的库来处理“表格相关操作”,避免“臃肿的表格框架”就再好不过了。
手动实现这些功能并不难,但更优雅的方式终究值得追求。
我认为这涉及数据存储方式。我真正想表达的是:编程语言本身应支持高级表格抽象/转换功能,例如分组、聚合、连接等操作。
没错,这就是LINQ+EF。人们长期厌恶ORM(确实有其道理),或许已经忘了它的核心价值。
(而且LINQ确实有语言级支持,因此它属于“语言本身”而非“库”)
实现这些功能的复杂度比大多数语言中任何其他一等原始数据类型高出一个数量级,且不存在能满足所有使用场景的明显“唯一正确方案”——似乎库和独立数据库才是可行之道,这也是我们当前的做法。
这听起来很像.NET中的LINQ(实际上通常与查询表的ORM兼容)。
啊,这样说就通了。感谢说明。
区别在于语义。
段落不就是句子的数组吗?句子不就是单词的数组吗?单词不就是字母的数组吗?这种递归可以无限延伸。最终你需要为事物赋予意义,而此时明确该事物 究竟是什么 就至关重要——因为结构体数组可以是多种非表结构的存在。
从历史角度看这很合理。表格在许多语言中确实存在,只是主流开发者使用的语言中没有。事实上,若按开发者之外的使用率排序编程语言,排名前列的语言 全都 采用表格类隐喻(SQL、Excel、R、Matlab)。
开发者使用的语言大多源自Algol。Algol是用于表达算法的语言,而算法本质上是对图灵机的抽象——后者基于无限一维磁带存储模型。这种一维存储模型被植入早期计算机、操作系统及编程语言中,我们称之为“机械同情”。
与此同时,另一些语言的诞生并未如此紧密地捆绑机器,而是更侧重于科学与数学计算。它们对这种一维世界观的关注度较低。早期语言如Fortran和Matlab就具备二维数据矩阵的概念,因为数学和科学领域本身就存在二维数据矩阵的概念。而C语言等则乐于通过指针数组支持这类操作,因其完美契合自身数据模型。
同样的逻辑也适用于1基索引与0基索引——Matlab、R和Excel采用1基索引,因其符合表格索引习惯;而C和Java采用0基索引,因其契合内存寻址方式。
对您观点稍作补充:C语言确实存在类似Fortran的基于存储映射的N维数组/张量,只是保留了传统的列优先/行优先差异,且采用笨拙的“多重[][]”语法。早期存在限制:数组维度需在编译时确定(至少最终维度如此),因为该特性当时处于半完成/半支持状态——且这种设计也契合线性数据模型。因此常见如 char *argv[] 这样的指针数组,或数值计算库中通过传入维度自行推导存储映射的实现。
>为何表格不能成为编程语言的一等公民?
Matlab 支持表格,实际上它存在多种相互竞争的表格概念。
Dplyr 对 data.frame 非常满意。R 语言是围绕表格数据构建的,其他统计语言如 Stata 亦是如此。
说SQL是操作表格数据的标准,就像说COBOL是金融交易的标准。基于当前使用情况或许成立,但没人认为这是长久之计。它们都基于过时的观念——认为编程语言应该像皮钦英语而非数学那样表达。
在R语言中,data.table本质上是另一种形态的SQL
精彩文章——但正如其他评论者所言,作者本应将论点论证设置为悬念式展开。
作者的优先级设定合理,基于这些标准选择R确实合乎逻辑。但数据科学家群体中并非人人如此。我从事数据科学八年,发现绘图和数据框处理仅是工作的一部分,通常还涉及文件操作、解析以及作者所称的“后勤工作”——而R在后勤处理方面表现糟糕。它同样不擅长编写可维护的软件。
若你更重视后勤保障与代码维护,结论将倾向Python——它在数据框处理方面仍表现不俗。若你同时频繁关注运行速度,Julia则更值得考虑。
这些优先级选择皆无谬误。我曾期盼Julia能更接近R的特性,但现实是它做不到——兼顾R的功能与通用编程的实用性,实属难事。
编辑:对了,还得提一句:我平时也教学生、带学生,总看到学生用pandas解决非表格问题,比如试图把图形当作数据框来表示。显然有些人特别喜欢用数据框搞一切——如果你是这样的人,建议重新评估你的工具,不过R语言可能更适合你。
>精彩文章
但其实不然。Python数据科学几乎必然需要使用numpy。所以他举的均值/方差代码例子根本是愚蠢的比较。numpy内置了数组的均值和方差函数。
即便采用他示例中的纯Python实现,某些语法也能大幅精简:
groups = defaultdict(list) [groups[(row[‘species’], row[‘island’])].append(row[‘body_mass_g’]) for row in filtered]
学习Python/numpy所需的认知成本与R语言相当。区别在于前者能将代码无缝集成到任何应用程序中。
> Numpy为数组内置了均值和方差函数。
即便在Numpy之外,标准库的statistics包也为常规可迭代对象提供了均值、方差、总体/样本标准差等统计函数。那些刻意让Python开箱即用代码显得糟糕的尝试,要么是为夸大问题而精心设计,要么是对Python及其标准库相关功能的刻意无知。
我不确定。Numpy拥有独立的数据类型、集合结构和语义体系,这些都与Python存在显著差异,我认为将其视为独立领域特定语言(DSL)是合理的。若它仅通过运算符重载为Python提供广播功能,情况或许不同,但Numpy存在的根本目的正是弥补Python在数据结构方面的诸多缺陷。
文章的第二部分就在这里:https://blog.genesmindsmachines.com/p/python-is-not-a-great-…
>我发现通常还涉及文件处理、解析等操作[…]
正因如此,我对Python和R的使用比例恰好是五五开:在高性能计算环境或服务器上用Python处理海量文件,然后获取百万字节级别的汇总数据,再用R在本地进行分析。
R语言 不擅长 循环处理数百个GB级文件,Python 不擅长 从摘要数据中提炼美观的洞察。各司其职。
我的经验是:用pandas做数据科学可行但笨拙丑陋。polars稍有改善,但仅是微小进步。而对我而言,duckdb则实现了质的飞跃。
如今我常在OLAP数据库上运行大型查询,将结果下载为Parquet格式存储在云笔记本虚拟机的本地磁盘,再用DuckDB直接读取这些文件进行深度挖掘。
笔记本最终呈现出清晰的SQL查询与结果(多数笔记本服务器支持带高亮和补全功能的SQL单元格),仅保留少量Python单元格处理那些命令式语言更擅长的边角案例。
所以当我看到文章末尾对比Python和R的段落时,忍不住想喊:“用SQL写出来不是更漂亮吗?” 🙂
咦,作为PolarS经常用户,我得试试DuckDB。
所以你是说更喜欢SQL而非数据框?我更倾向于数据框和原生语言环境。
Duckdb同样能读取和操作数据框。它虽有自有存储,但其他表存储——比如我提到的parquet文件、csv文件,甚至pandas和polars的数据框——都是平等公民。Duckdb能让你快速而灵活地查询它们。
作为偶尔使用R语言的Python程序员:当然可以。Python并非专精于任何领域的语言,而是几乎适用于所有场景的优秀工具——这始终是它的核心优势。
若你从事全职数据科学工作,就该学习R语言。即便初学时(对C语言风格背景者而言)它显得异常诡谲,甚至难如登天; R语言是为统计学家的工作方式和思维模式设计的,而非计算机程序员的思维模式。若你整天从事数据科学工作,就该像统计学家那样思考和工作,用R语言编程——它看似扭曲思维的特性其实未必是坏事,因为统计学家的思维方式本就需要与程序员不同。
不过我几乎全天候都在用Python工作。
最后一个示例中的纯Python代码过于冗长。
可重写为:
以及
改为:
> (n – 1)
有趣的是有人会手写标准差函数并 包含 贝塞尔修正项。通常我手动重写标准差函数,是因为担心实现者盲目套用修正项却未考虑其对具体分析的实际意义。至少该函数的正确命名应为
sample_std_dev。这种不一致性实在令人遗憾。标准库的statistics模块提供了两个独立函数:stdev用于样本,pstdev用于总体。Numpy和pandas都提供带ddof(自由度)参数的.std()方法,但numpy默认值为0(总体),pandas默认值为1(样本)。
不同意。
首先,原始代码清晰易读且直观传达了功能逻辑。而你的示例为追求巧妙而牺牲了可读性。
清晰的代码(即使冗长)远胜于刻意耍小聪明。
依我之见,初次阅读此类代码时,或许更倾向第一种写法。但读到第20遍时,可能会更倾向第二种。当你理解实现逻辑后,往往更青睐能处理大型项目复杂性的精炼语法。只是初看时难免觉得“过于花哨”。
我用Python理解式和JS匿名/箭头函数时也遇到过这种情况。
当你习惯了语言的“怪癖”(只要它们被视为惯用表达),这些特性便不再显得古怪,通常适应起来也很快。
即使使用非惯用语法也能达到同样效果,唯一的问题是只有你自己能理解它。
使用标准库中常见的实用工具来避免重复造轮子,难道不算“干净的代码”?
defaultdict在现代Python中无处不在,其概念远非难以理解。
我觉得这个比喻不太恰当,它与我理解的“重新发明轮子”属于不同层面。后者更像是试图在没有必要的情况下,为程序增添某种新奇的外在表现形式。比如用自定义内核驱动重新实现共享内存作为进程间通信机制,尽管它根本没能实现共享内存无法做到的事。
这两个例子差异如此微小,我不明白楼上评论为何要大做文章。
代码清晰度本就主观。我认为第二种更易阅读,因为需要浏览的代码量更少。阅读代码时我习惯性地将其拆解重组,因此对第二种做法毫无异议。而第一种写法篇幅加倍,阅读时间也大约翻倍。
第二种版本最符合惯用表达。
很有意思!感谢大家的回复。我并非Python母语者,对Python的掌握也不如在座某些朋友深入。
话虽如此,我在此改变立场同意使用标准库,但为增强可读性仍建议单独声明'key'赋值。
我会保留显式key=赋值,因其不仅是单个字面量。但除此之外,第二种写法更符合惯例且可读性更高。
我在Julia中用TidierData.jl尝试了这个方案,效果与R版本相当接近。
我不确定最后那个示例除了作为反Python的讽刺外还有什么意义。如果手动实现标准差之类的计算,那不是现实世界的编程,而是本科生折磨包——这种做法应该在STEM学士学位阶段就终结。
当然里面有大量循环之类的东西;你暴露了R和Python所有包底层必须执行的操作。
> 这不是现实世界的编程
很明显,这篇帖子聚焦于学术研究实验室的工作场景。在此背景下,我认为多数观点相当合理。但就我个人而言,使用Python在现实世界中最大的价值在于能更紧密地与工程团队协作(即使对方并非Python团队)。
在我职业生涯中曾将R代码部署到生产环境,感觉它脆弱得令人发指。
R语言在探索性数据分析(EDA)方面堪称 绝佳 ,但用于迭代构建大型软件项目却效果欠佳。R虽拥有强大的包管理系统,但在需要中间层抽象时便显得力不从心。
确实,对我而言R从来都不是首选的编程语言…它凭借强大的包库和尖端统计方法,是数据分析领域的统计巨兽,而非生产工具。
我实在不理解作者的抱怨。他们举的唯一具体例子是:认为不用Pandas库的Python实现相同功能会冗长丑陋,因此断言Python不适合数据科学。
这要么是拙劣的论证,要么是幼稚的谬论——视角度而定。
Python并非为数据科学而生,它不是该领域的专用语言。MATLAB虽可说是为科学计算设计的,却在StackOverflow喜好指数中位列最不受欢迎语言榜首。
不妨换个角度思考:优秀的编程语言如同城市的天气。我当然渴望常年保持23℃的宜人气候,但若身处荒芜之地且无知己相伴,我还会选择那里吗?恐怕不会。
顺便说一句,Python就像瑞典或芬兰——每年有半年天气糟糕透顶,却依然蓬勃发展。
附注:我认为这篇文章的标题有点噱头(讨论价值不高),因为它极具争议性,且无人能对此给出百分百正确的答案。或许将其视为观点文章更为恰当。
我目前正把Python当作兴趣语言学习。靠C/C++和C#赚钱。最大的问题是找不到优质的最新示例。我花了一整天才弄明白格式化字符串有四种(我记得是这样)实现方式。这种语法“臃肿”让简单的print语句都难以消化。我甚至懒得碰Python 2,只用3.0版本。虽然用空格分隔代码块听起来很吸引人,但实际操作时必须依赖能批量缩进/取消缩进的编辑器,否则永远搞不定格式。
你似乎在无谓地增加难度。
字符串处理直接用f字符串,其他全抛掉。调试时甚至可以这样写:
关于代码块缩进,你用的是什么编辑器?几乎所有现代编辑器都支持选中代码块后用Tab/Shift+Tab实现缩进/取消缩进。
VS Code和PyCharm都是免费的Python编程利器,它们都配备了完整的调试器——这对学习语言而言价值连城。
我认为他们的核心观点在于:对零基础的Python学习者而言,众多实现方式(如字符串插值)中究竟哪种才是“正确”/符合惯例的做法并不明确。
十五年前,Python程序员常引用《Python禅》嘲讽Perl:“实现某件事的方式应当只有一种——最好是唯一一种”。这与Perl的座右铭“实现方式不止一种”形成鲜明对比。
可悲的是,《Python禅》如今已沦为彻头彻尾的谎言。
> 但现实中你必须使用能批量缩进/取消缩进的编辑器,否则我永远搞不定
你用的什么编辑器连这都做不到?记事本?
在文章中
> 对比这段充满逻辑运算的等效代码,我仅使用基础Python语言特性,未借助任何特殊数据处理包:
他显然不了解Python标准库中的统计包(https://docs.python.org/3/library/statistics.html)。当然,若不熟悉Python用法,确实会产生大量冗余代码。
我本以为作者会合理抱怨工具链问题,包括代码检查器、格式化工具和包管理器。近年来随着Astral的ruff、uv和alpha阶段的ty工具出现,情况已大幅改善。
但文章却宣称那些奇特的语法更易读。我认为这主要关乎库的选择——坦白说我对matplotlib和R语言的ggplot同样不感冒。但我不认为这是语言本身的问题。
我原本希望能找到一些性能基准测试,或者比对某些代码块的个人感受更具参考价值的内容。别误会,虽然我用Python写过大量生产代码,但我也并非Python的铁杆粉丝。提到臃肿的模板代码……恐怕作者应该去看看Java或任何现代JavaScript项目。
Python之所以成为数据科学的理想语言,在于其广泛普及性与可读性。若采用Clojure、Common Lisp、Julia等冷门语言,多数人将无法理解代码内容,这将阻碍同行评审——而同行评审正是科学研究的基石。若仅以“任务适配性”为优化标准,确实存在优于Python的语言。但若以“科学价值”为衡量尺度,Python(及R语言)无疑是最佳选择。在科学领域,完成任务远远不够——他人必须能读懂并理解你的工作成果。
顺带一提,人工智能并未带来帮助,反而催生了一代只会编写提示词却不懂代码原理、更无力进行同行评审的科学家。
Julia我无法评价——从未使用过; 也从未用Common Lisp做数据分析(感觉它对现代数据形态不够“数据导向”),但Clojure绝非“冷门”——初见时或许怪异,十五分钟后便会发现它实属最直观合理的语言之一,甚至比Python和JavaScript更简洁。默认不可变特性让代码逻辑推演轻松得多。天啊,它才是真正的数据导向语言——居然没人用简直不可思议。多数人甚至从未听闻。
我尝试过学习Clojure,但许多JVM托管语言都需要Java基础。Scala、Kotlin或.NET平台的F#也一样。
早期工具链还高度依赖Vim或Emacs。如今有了VSCode之类的集成开发环境,或许都变得简单多了。
它本身不需要任何Java知识,但文档有时会默认读者对JVM有一定了解——初学时这点挺让人抓狂。比如直接使用“类路径”这类术语却不作解释。不过如今借助大型语言模型,这些障碍已微不足道。
若需使用Java,除“创建类实例并调用方法”外,其实无需深究Java知识。我实在不想学习Java这种“恐龙级”语言,但能调用海量Java库确实帮过我无数次。通过REPL交互式探索成熟Java库的过程既有趣又令人愉悦 🙂
话虽如此,我至今仍不会写Java的HelloWorld程序
PS:赞同Emacs的评价。我热爱Emacs…但它专为超级极客设计。同时学习Emacs和Clojure简直是疯狂的门槛(而且Emacs绝非外界宣称的那么简单)
以上说法完全不成立。我当年完全不懂Java就入门了Clojure,十年后的今天,在成功构建部署了无数项目后,依然对Java一窍不通。播客《Clojure apropos》的联合主持人Mia曾是我的同事,我们合作过多个团队,她把Clojure当作人生第一门编程语言。后来她尝试学Java时,发现和Clojure相比简直怪得离谱,震惊不已。况且Clojure完全无需JVM环境——比如配合nbb就能运行。我用它实现浏览器自动化测试,比如搭配Playwright。
工具链同样强大——我用Emacs,但许多同事朋友选择IntelliJ、Vim、Sublime和VSCode,其中不乏从Atom迁移过来的开发者。
这或许对你不成问题,但确实困扰过许多人。我最初确实读了三本Clojure书籍。REPL和列表等基础操作固然简单,但工具链相比我习惯的配置相当简陋(我喜欢Lisp,但Emacs需要投入精力)。此外当时许多教程明显假设读者熟悉Java,尤其需要理解Java堆栈跟踪调试。
我是Common Lisp爱好者,但并非数据科学家。为何建议避免用CL做数据分析?无意争论,只是好奇你的使用体验。
我对用CL分析数据的经验有限,因为存在根本疑问:既然已有另一种在数据处理上堪称完美的Lisp语言,何必选择CL?
Clojure 的集合体系不同于传统 Lisp 中的列表,它基于可组合的统一抽象,默认采用惰性求值,且数据结构直观易读。相较于任何语言(不仅限于 CL,甚至包括 Python),其集合更易于内省且不那么“不透明”,尤其擅长处理异构数据。Clojure 凝聚的數據操作特性是 Common Lisp 的列表与符号无法企及的。
作业需求另当别论,自1985年左右起,极少有严肃的Common Lisp程序将列表和符号作为核心数据结构。
Common Lisp拥有O[1]向量、多维数组、哈希表(即Clojure的映射)、结构体和对象。它支持集合运算但不强制成员唯一性。它还支持大整数、多种精度浮点数、无限精度有理数及复数。更不用说字符、字符串和位逻辑运算了。与Clojure的核心差异在于Common Lisp数据结构并非不可变,但这与“Common Lisp缺乏现代数据结构库”的论点并无直接关联。
Common Lisp从未局限于“列表处理”。
没关系,我认为根本没人知道如何正确编写Julia代码。使用一段时间并关注社区(观看讲座、查阅论坛等)后,我发现它似乎缺乏代码质量的概念。人们只是把随机代码扔到墙上直到它开始工作。考虑到用户多为科学家,这种做法倒也合乎情理。
> Python之所以成为数据科学的理想语言,在于其广泛普及性
虽然我原则上认同,但这也导致了所谓的“VB效应”。当年VB作为标准课程在每所学校教授,让每个孩子都成了“计算机天才”。我曾不得不修复许多由“天才外甥”编写的遗留代码库。
同行评审是科学研究的基础,但在机器学习领域,评审者几乎从不检查代码,而Python包管理机制几乎无法复现。显然我们尚未达到理想状态——无论是否使用Python。
文章文笔精湛,却将核心论点推迟至续篇讨论,未能直面自身命题。现阶段仅暗示Python因需专用包而欠佳(反例R语言同样依赖包系统)。
“续篇”已发布:https://blog.genesmindsmachines.com/p/python-is-not-a-great-…
完全赞同。作者最重要的示例是两个高度相似的代码片段,二者都相当出色。
我编写Python已有约20年,从事数据科学/机器学习工作约15年。尽管最初是Python程序员,但我曾有整整五年时间只使用R语言。我真心喜爱R语言的诸多特性,坚信开发者对R的贬低实属不公…但过去五年我专攻数据科学领域时只用Python,确有充分理由。
> Python在深度学习领域表现优异。PyTorch成为行业标准自有其道理。此处讨论数据科学时,我特意排除了深度学习范畴。
职业生涯中我编写的深度学习代码寥寥无几,却频繁运用GPU和可微编程处理非深度学习任务。总体而言,Python更易编写利用硬件的量化程序,且当问题超出内存容量时,它能提供更多解决方案。
> 我在计算生物学领域运营研究实验室已逾二十载。
这二十年我几乎完全在工业界工作,而我认为Python更胜一筹的 关键 原因在于:当使用真正通用的编程语言时,它能极大简化与工程其他环节的对接。虽然我从未在纯Python团队工作过,但使用Python通常能更轻松地将机器学习/数据科学解决方案投入生产环境。
> 我在此定义的数据科学涉及大量交互式数据探索以及快速的一次性分析或实验
这再次印证了前文所述差异。根据我的经验,这可称为所有数据科学工作的“第一步”——即理解问题并降低风险。但绝大多数代码和工作都与交付可扩展产品相关。
或许有人认为这不属于“数据科学”范畴,但若真如此,在多数团队中你将难以立足——至少在我参与过的团队里是如此。
综上所述,我对R与Python的体验可归结为:若最终产出是PDF报告,R更胜一筹;若最终目标是交付产品,Python则更胜一筹。而我的经验是,在大学实验室之外,仅需交付PDF的职位对数据科学从业者而言并不多见。
Python在表格数据分析和绘图方面表现欠佳——这恰是本文的核心议题。R显然更胜一筹,甚至Tableau、Matlab、JMP、Prism乃至Excel在多数场景下都更胜一筹。Pandas+seaborn虽有长足进步,但seaborn仍存在令人沮丧的局限性。而pandas本质上已构成独立的编程语言体系。
若数据已呈表格化,你仍选择Python,那多半是为了为下一份工作学习Python,而非因其是当前任务的最佳工具。Python相较其他选项的唯一优势在于$$$。相比死守R语言,掌握Python将使你更具就业竞争力。
原因在于Python是数据与机器学习 工程 领域最优语言之一,而这恰恰构成数据科学岗位80%的核心工作内容。
> pandas本质上是另一门独立的编程语言。
我认为dplyr/tidyverse之于R,远比pandas之于Python更像独立语言体系。
…除非你的数据工程工作基于数据库,这种情况下R的dbplyr远胜Python任何解决方案。
构建数据科学管道时,本质上包含三个独立步骤:
[数据预处理] –> [数据分析] –> [结果呈现]
无论是Python还是R,都未能在所有环节表现出色。
原文似乎聚焦于Python在数据准备/处理环节的挑战,主要指出Pandas及“原始”Python代码在数据处理中的局限性。
此问题可通过切换至duckdb和SQL等工具来解决。
至于数据分析领域,Python和R各有专长,具体取决于应用场景。同样,其他专业化语言(如SAS、Matlab)仍广泛应用于特定领域。
我个人认为Python和R在结果准备方面都存在一定难度。Stargazer用于导出回归表格尚可,但表现并不出色。在ggplot生态系统中,R的绘图功能可能更胜一筹(我知晓其Python移植版本)。
我希望更多人使用Julia。几年前我为心理测量学博士论文中需要的新算法[1]重写了部分MATLAB代码,Julia展现出卓越的开发体验——更关键的是,代码运行时间从60分钟缩短至20分钟。
[1] https://link.springer.com/article/10.1007/s11336-017-9581-x
对于撰写心理测量学博士论文的整个项目时间线而言,节省40分钟有多重要?
一旦数据经过清理并规范化处理,选择哪种语言就成为个人偏好问题。
工作经验表明,90%的工作是收集、清理和转换来自不同来源的数据。在这方面,Python提供了更多可选方案。
我认为从“Python vs R”之争中得到的启示是:人们更倾向于使用一种既能胜任数据科学任务又具备通用性的语言,而非专为数据科学设计却存在规模不经济问题的语言。具体来说:假设某款新型数据库刚问世。此时,既需要将其集成到应用程序中,又需要从中提取数据进行分析的用户群体,共同推动了Python库的需求。这种协同效应远优于为满足两类需求分别开发两种语言库的情况。
你提到了使用Python输出结果的优势。
我认为在将输入数据整理成可操作的干净数据集方面,Python相较于R这类分析专用工具同样具有显著优势。
作为Python和R的深度用户,我的结论也类似:
处理数据清洗、探索或可视化时,我必然选择R;
构建机器学习/深度学习模型或操作大型语言模型时,则通常选择Python。
如今借助Quarto,这些操作在同一文档中就能轻松实现。
Python存在若干语言层面的根本性缺陷,其运行速度与精度高度依赖集成库绑定。
Julia支持嵌入R与Python代码,并提供强大的数据集深度挖掘工具:
https://www.queryverse.org/
这是我数十年来见过的首个能将完整范式浓缩为单字符语法的语言,在许多场景下甚至超越了C语言和Numpy的性能。=3
Julia支持者竟无凭无据地污蔑流行语言“存在根本性缺陷”,这实在讽刺至极。
https://yuri.is/not-julia/
这就像那些转发迪杰斯特拉倡导0基索引的信件,却从未读懂或理解自己转发内容的人。
索引语法与Julia在正确性缺陷和陷阱代码方面糟糕的历史有何关联?
当然,若仅看缺陷发生频率的历史数据…所有软件都糟糕透顶…
https://github.com/python/cpython/issues
某些喷子在博客上拿v1.0.5版本里陈年旧案的_已关闭_工单大做文章,试图证明Julia有多糟糕…这种论证实在站不住脚。Julia连绘图库输出都内置了回归测试功能,因此问题通常能通过严谨的可复现性保持已解决状态。况且在任何LLVM语言代码中运行合理性检查本就是明智之举。
祝好运 =3
Python的线程与计算错误问题由来已久。它虽是广受欢迎的集成“粘合剂”语言,却依赖SWiG封装器来规避诸多未解决/无法解决的缺陷。
这并非“抹黑”,而是众所周知的语言局限。或许你的环境与我的运作逻辑不同。
人们竟对如此琐碎平庸之事投入情感真是荒谬。Julia当前版本v1.12.2可能存在差异,但Queryverse确实很有趣=3
该示例用SQL编写会更合理。按作者逻辑,这岂不是说明SQL是数据科学的理想语言?况且SQL原生支持表格结构。这种结论显然荒谬,暴露了本文推理的肤浅性。
这篇文章令人失望。我日常使用Python和Pandas,能举出更笨拙的工作流实例。最常见的是遇到数据框[(dataframe.column1 == 某个值) & ~dataframe.column2.isna()]这类构造,这恰恰说明Python语法在此场景下存在缺陷,不适合此类操作。遗憾的是目前没有替代方案,而R语言也未必更优雅,同样存在大量丑陋的实现。
Julia虽是选项之一,但存在严重缺陷——例如从命令行启动脚本时的冷启动速度极慢,使其无法胜任命令行工作流。
若非如此,就只能转向编译型语言,但需权衡其取舍。
> 遗憾的是别无选择,而R语言也未必更优雅,其中同样充斥着诸多丑陋的设计。
你试过Polars吗?它能有效避免你展示的代码中低效创建中间布尔数组的情况。
> 还有Julia——它存在严重缺陷,比如从shell启动Julia脚本时冷启动缓慢,这使其不适合命令行工作流。
Julia在启动速度上已显著改善,尤其在绘图方面。基于REPL或笔记本的开发模式确实更优,能将编译成本分摊到多次执行中。编译机制正日益模块化,既有基于包的预编译模式,也有提前编译模式。我特别欣赏其典型编译流程是隐式步骤的设计,这使得工作流更接近脚本语言而非传统编译语言。
同时值得肯定的是,传统的前置静态编译至二进制可执行文件的部署方式如今也已可用。
在R或Python中开发一天后,我常开始后悔没用Julia——因为我知道若用Julia编写的昨日代码本可运行得更快。问题本质在于:我愿为当下节省时间,还是为项目生命周期付出代价?
> 你试过Polars吗?它能有效避免你展示的代码中低效创建中间布尔数组的问题。
问题通常不在于效率,而在于语法冗余。Polars在某些情况下确实能消除冗余,但整体反而更赘述(显然是设计使然),这在探索性数据分析中很快就会令人烦躁。
这取决于“数据科学”的具体定义。就随机模拟而言,C++与Eigen库的组合无可匹敌——借助Eigen的“零成本抽象”,既能获得高级代码的可读性,又能享受低级代码的性能。
若数据科学指的是加载数据到内存并运行预设程序处理回归、分类等任务,那么Python表现出色——它主要在后台调用C/FORTRAN二进制文件,因此Python本身的开销相对较小。
猜猜看,用专业化且固化的库(Pandas)完成相对复杂但标准的任务(过滤和聚合企鹅样本),比用基础列表和字典“徒手操作”更高效。
代码更简洁、效率更高、出错率更低,数值精度也可能更优——仿佛Python拥有了与R比肩的精心设计的库生态系统。
Python的普适性正是其受欢迎的关键。借助成熟库可实现GPU数据双向加载,必要时支持内存映射。若循环效率低下,可将热点代码重写为Rust或C语言。多数文件格式读写仅需几行代码。
我基本认同核心观点,但反对用底层代码论证语言缺陷的做法。具体而言,若没有tidyverse生态,R语言的表现也绝非尽善尽美。
尽管承认这令人不快,但Python之所以成为数据科学利器,几乎完全源于其庞大的用户群体——这种普及性本身就是优势。
本文的核心谬误在于将面向生产系统设计的通用语言(Python)与专为交互式分析打造的领域特定语言(R)相比较…切忌混淆概念,因为将R代码产品化通常需要重写为其他语言。
Python本质上只是具备以下特性的语言:
1. 代码易读
2. 便于扩展为科学数据工作者偏好的语言
攻读硕士期间,我们在从事天体物理研究时曾修改numpy源代码并贡献了若干改进。
Java和R语言虽有类似工具,但我们第一学期学过C语言,Python更易阅读,且不同于MATLAB,numpy无需许可证。
当数据科学兴起时,该领域充斥着从事类似工作的物理学家。他们带来了自己的工具,其他人亦然。
Python的核心优势在于它能吸引毫无编程经验的新手。他们或许模糊地知道想让计算机先执行这个操作再执行那个操作——命令式编程正是他们的起点,而Python完美契合这种需求。它最初作为脚本语言设计,主要用途确实是串联其他工具。它始终擅长此道,这也是九十年代的主要应用场景。
当Linux发行版开始大量依赖Python脚本(如红帽和Debian)后,Python迅速走红。其副作用是早期便广泛存在于众多Linux和Unix系统中。2000年代初及九十年代末的科研人员普遍使用运行Linux/Unix的工作站,因此Python作为现成的易用工具自然成为首选。
正因其易用性,大量用户由此入门。于是形成独特发展轨迹:各领域研究者代代相传,将Python视为首选工具。它从未在任何领域达到顶尖水平——这本就不是开发目标。相较某些数据科学家偏好的替代方案,Python运行稍慢,语法略显冗长笨拙,且缺乏其他语言的诸多特性。等等。但这些都不重要,因为它简单易用。初学编程的用户需要的是能理解的简单工具,而非数学家或计算机科学家追求的理想化语言。
Python相当于现代版的BASIC——在Python诞生前,BASIC曾扮演过这个角色。它本身并不惊艳。但早期家用电脑将其作为操作系统组成部分。例如我人生第一台电脑Commodore 64的主操作系统体验,就是通过交互式BASIC命令行从磁带加载游戏。
编程语言本质上具有网络效应;全球多数人学习英语是为了与同样懂英语的专业人士交流,而非出于对狄更斯的热爱。
我认为(也基于自身经验)Python胜出是因为团队其他成员都懂它。我更偏好R语言,但我们的网页开发者不懂R,而编写团队成员能审查、扩展和维护的代码对我更有价值。
现实中它胜出是因为易于上手而非完美契合
尽管我个人偏爱Python胜过R语言,但不得不承认这个观点有道理。不过我也认为R并非数据科学的“完美”选择——它存在明显短板,比如上次尝试时,编写自定义循环(或用map/reduce实现功能等效)的体验相当笨拙。
另一件事是,R语言的许多优势其实源于tidyverse生态。这固然要归功于R作为可扩展语言的特性,它让优秀的API设计师得以大放异彩,但我认为Python语言完全可以拥有类似的库。事实上它已经有了plotnine库(虽然我还没试过Polars,但至少它的API看起来更统一)。
文中使用的纯Python/标准库示例(以及刻意回避数据科学类扩展库的做法——这本就不是多数人使用Python进行数据科学的方式)实在…欠妥?(此处“欠妥”意指刻意回避标准库功能,以凸显作者后续抱怨的问题。)
更优的纯标准库版本应为:
从事计算生物学研究数十年,使用过十余种编程语言。我认为R语言在数据科学领域更胜一筹,但实际工作中几乎每次都选择Python——因其拥有更丰富的库资源,且更容易找到精通Python的软件工程师和合作者。不过R语言能编写更简洁的代码,减少无提示错误,其1索引特性也让生物序列处理轻松许多。
恕我直言?更少静默错误?R语言在宽容解析用户意图方面暗藏诸多陷阱。这固然便利于探索性分析,但用于生产代码时却脆弱得多。
仅举一例:R采用1索引机制。但若访问向量myvec[0]却不会报错。反之,当向量长度为3时,访问myvec[10]会返回NA(本应合法的值)。更离谱的是,赋值操作会无声扩展数组:myvec[15]
<-3.14 执行后,数组末尾会自动填充NA值。据我经验,R语言堪称“错误处理之王”——明明早该报错的代码,它却能若无其事地吐出荒谬结果。
从实用角度看,Clojure在数据处理上表现优异。通过clj-python库还能调用Python库资源。
近几年我目睹了 Clojure 社区为提升其数据科学吸引力所做的扎实努力。不妨关注 Scicloj[1] 团队及其数据科学栈/工具包 Noj[2](仍处于测试阶段),以及高性能表格数据处理库 tech.ml.dataset (TMD)[3]。
– [1] https://scicloj.github.io
– [2] https://scicloj.github.io/noj
– [3] https://github.com/techascent/tech.ml.dataset
值得强调的是,你并非在嫁入某个库的生态系统。其中包含许多可独立使用的组件。我处理气候数据时基本不用Scicloj的工具,但tech.ml.dataset却被我广泛应用
第二部分在此:
https://blog.genesmindsmachines.com/p/python-is-not-a-great-…
免责声明:我对R或Python并无偏见,亦无倾向性。
Python语言本身或许并非数据科学的理想选择。但作者完全可以借助Python中的Pandas、Polars或其他数据科学相关库/框架,实现原本计划用R语言编写的任务。我既能看懂她的R代码片段,也能理解其Pandas代码片段。
这篇文章读起来就像在说:“看啊,我所有食材都从零开始制作,这有多难!”
他们基本上主张使用R语言。我认为这取决于他们对“数据科学”的定义,以及该从业者是否仅从事数据科学工作。若情况如此,R语言或许更合适——毕竟其整个职业生涯都将立足于该领域。但若他们走的是通用计算机科学路线,那么学习Python可能比R更有益,单纯因为Python能满足其他用途。
> 无论如何,我在此不再深入讨论。我也不会考虑Matlab或Mathematica这类专有语言,或是像Octave这样缺乏完善生态系统的冷门语言。
我认为对多数程序员而言,R属于同类。R之于他们,正如Octave之于本文作者。R固然不错,但他们真想学这种“小众”语言吗?即便它某些特性优于Python?值得为掌握全新范式、语法和库生态而费神吗?
有点晚了
“不完美”未必等于“糟糕”,它可能被解读为“优秀”甚至“卓越”。诚实的标题本应明确说明作者对其适用性的具体评价。
作者刻意避免直言Python是糟糕语言,恰恰印证了它的适用性。当然,这还得益于数据科学实践中的主流地位。
这简直需要一场Python与R开发者的A/B编程速度测试。
或许对长期使用者而言R很合适?但作为偶尔需要数据分析的软件工程师,我更倾向于使用熟悉的工具而非R。R作为语言实在过于复杂。
值得一提的是,Kotlin团队正持续为数据分析增添酷炫功能与工具。https://kotlinlang.org/docs/data-analysis-overview.html
结尾不妨加上“Python并非优秀语言”。
那么Python是否算成功语言?绝对是。
R语言数据科学从业者多来自生命科学或统计学领域,而Python数据科学从业者则多源于工程类背景。当然这并非绝对,但符合普遍规律。
近期我注意到Python正被大力推广至所有数据科学相关领域。客观而言,Python未必是最佳选择——尤其在统计领域。但当某种工具成为“行业标准”后,即便存在适用性问题,要改变现状也异常艰难。
R语言之所以卓越,部分得益于迪·库克、哈德利·威克汉姆和谢毅辉等开发者打造的理想化软件环境。
R语言的另一优势在于:任何函数都能彻底改变参数的评估方式,这使得tidyverse套件能实现诸如在数据框上下文中评估参数、添加管道运算符等语言特性。虽然将这种功能交到统计学家手中风险极高,但它确实比Python提供了更丰富的语法创新空间。
与Python类似,R是双层语言系统(2 (+…))。随着问题规模扩大,需借助C/Fortran后端提升性能。
Julia和Nim[1]分别代表动态与静态单层语言系统,二者均支持用户自定义运算符和宏。个人而言,我对Julia的表面语法颇为反感,且并不整天沉浸在PLang REPL/emacs环境中。当然,Julia和Nim都未到难以调用C/Fortran的程度,但其社区确实倾向于直接用新语言实现功能。
[1] https://nim-lang.org/
他们的批评似乎集中在两个方面——pandas的局限性及内置函数支持不足。
就个人经验而言,Polar已解决我使用pandas时遇到的多数“棘手”问题。它运行速度更快,拥有符合人体工学的API,与pandas无缝兼容,并支持强大的自定义扩展。我们必须意识到pandas如今已有近20年历史。
我承认Shiny是卓越的包,但考虑到大型语言模型将编写大部分代码,其重要性已有所降低。
Shell才是数据科学领域的最佳语言。为数据获取、清洗、转换和可视化分别选择最优工具,再凭借文本作为通用互操作协议、文件作为数据中间阶段存储载体的天然优势,将它们无缝串联起来。
最妙的是编写–help文档后,可将这些工具加载至LLM中,让模型自行理解操作逻辑。
来辩论啊。
使用Shell脚本实现的redo[1]功能已成为我处理多步骤数据问题的首选方案。它能轻松追溯数据获取、清洗、转换等每个环节的操作过程。
我在Shell脚本中使用mlr、sqlite、rye、souffle和goawk,并通过visidata交互式审查中间文件。
1. https://redo.readthedocs.io/en/latest/
JavaScript在网页开发领域同样算不上理想语言,然而……
等等,这难道不是一个实例吗?它恰恰证明R和Python的实现方式几乎完全一致……
我满怀期待地准备见证那些令人信服的精彩示例和论据,最终却一无所获(除了引号和括号……)。
令人失望。
当数据科学成为主流时,Python确实是数据科学领域的绝佳语言。
它易于构思结构(迭代器),易于扩展,拥有优秀的社区生态。
正因如此,人们开始通过库文件不断扩展它。
如今替代方案已层出不穷。
作者是否在说:Python+Pandas几乎可媲美R,但纯Python的性能不及R?
我不得不认为Python与R实力相当——毕竟需要时我仍可选择Pandas。我的理解有误吗?
你漏掉了开头句的“几乎”。
而且我们并未定义“优秀”的标准。
数据科学是我认为Python尤其擅长的领域
标题修正:若没有pandas/polars/ibis,Python绝非数据科学的理想语言
请仔细阅读原文。文中明确以pandas代码作为示例。
所以…这篇帖子是在嫉妒Python吗?
问题在于它背后的势头太强劲,难以修正方向。PyTorch如今已是巨人。
> 我认为人们严重高估了Python在数据科学领域的地位。它存在诸多值得注意的局限性。许多数据科学任务我宁愿用R而非Python完成。
R语言属于高度专业化的语言,而Python则更具通用性。
坦白说,R语言未能实现进化。Python凭借Jupyter胜出——我在大学里随处可见它的应用。R语言虽也有使用,但基本局限于统计学相关课程。
或许R在特定领域更胜一筹,但Python拥有更强的发展势头,因而占据主导地位。这正是现实情况——就像推土机以迅猛速度向前推进。
> 我说:“这很好,但能否快速用另一种方式绘制数据?”
好吧…他同样需要调整R代码对吧?而且找到相关优质资料实在困难。他说有大学教学经验,我也有,但我的经验是人们掌握Python远比掌握R轻松。你会发现放弃R的学生远多于放弃Python的,这也是不争的事实。
> 它们似乎足够繁琐或令人困惑,导致我认为理应简单的请求往往难以实现。
反之亦然。随便挑个Python库实现某个酷炫功能,再让R学生照做,我敢打赌他会遇到同样的问题。
> 很多时候,我发现本该用几行简单R代码实现的功能,最终却变得冗长复杂。
好了,这分明是在挑刺。我直说吧——这就是在挑刺。
我写过大量Python代码,也写过不少R代码。现实中90%的应用场景里,R代码绝不可能比Python代码更简洁。抱歉,事实就是如此。R语言更冗长。
> 以下是采用tidyverse方法的R语言相关代码:
这简直像Perl。他们同样缺乏适应性。R注定会失去市场。
这位教授尚未意识到,自己正因无法看清X优于Y的事实,而逐渐沦为活化石。
> 坦白说,R语言未能进化。Python凭借Jupyter胜出
Ju = Julia Pyt = Python Er = R
R不仅支持Jupyter,它从一开始就在那里。我从未写过一行R代码。人们对工具的认知如此匮乏,实在荒谬。
> 我认为人们严重高估了Python在数据科学领域的地位。它存在诸多值得注意的局限性。许多数据科学任务我宁愿用R而非Python完成。1 我相信Python在数据科学领域如此普及,既是历史偶然,也因它在多数场景下勉强可用,而非其天生适合数据科学工作。
Python无需在任何单一领域做到顶尖,只需在众多领域具备实用性即可。你可以让精通完全不同软件领域(如网页开发、运维开发、系统管理等)的人员接触数据科学领域,而无需他们学习全新的语言和工具链。
但这并非它在数据科学领域被广泛采用的原因。许多数据科学家终日使用Python,甚至从未考虑过转行。
它之所以被数据科学界采用,纯粹是因为数据科学界本身就在使用它。
它之所以被数据科学界采用,是因为没有其他语言能提供如此完善的库支持体系。
而它能获得这种前所未有的支持,正是因为从诞生之初就明确聚焦于语法和(感知中的)简洁性。
此外,它对算法工作的友好性也产生了某种累积效应。
Guido的长远战略击败了众多其他强有力的竞争者。
我认为大多数数据科学家未能察觉的关键在于:他们使用Python并非因其满足需求,而是我们两次辜负了他们。
1. 数据科学家 并非 程序员,为何需要编程语言?他们应使用的工具并不存在。这些工具需要程序员开发,而我们提供的却只是…更多编程语言。
2. 现代软件的核心困境在于:现代编程语言最重要的特性是易读易写,而这一特性在多数主流语言中却明显缺失。
他们陷入两难境地。没有编程语言就无法完成工作,但可选语言屈指可数。Python最终获得如此完善的库支持,本质上是因为他们别无选择。
当首批科学库为Python编写时,其他语言甚至不考虑可读性或便捷性。当时的选择更像是C/C++/Fortran与Python的对决。
随后Python进入自我强化的循环:科学界不断探索改进Python对数据分析所需交互式工作的支持。想想 ipython → jupyter → jupyter 分支及其他以 Python 为核心的笔记本系统。
因此当数据分析演进为数据科学和机器学习时,GPU 优先的库供应商早已面对大批精通 Python 的用户群体。
如今仅凭这些用 json 包装的脏 Python 代码就能调用数百个 GPU,简直不可思议。
但数据科学绝非孤岛。
个人项目随心所欲即可,但若想让模型直接投入生产环境,请选用更适合生产部署的方案。
将R模型投入生产相当痛苦,常规做法是直接重写为非R语言版本。
我对直接将数据科学代码投入生产环境深感失望。这通常会变成难以维护的混乱局面。
若先用R编写代码,再转译为C语言(更优方案:用英语重构代码,将R作为辅助注释,再由他人转译为C),至少能确保你思考过解决实际问题所需的抽象概念和操作逻辑。
部分原因如此,但更关键的是——所谓“数据科学”工作中90%并非直接分析。
你得先获取数据。是否需要爬取?因为Python擅长爬取?哦,爬取后发现数据格式是ObtuseBinaryFormat0.0.LOL。测试阶段发现——真巧,有人写了Python转换器。接着要清理所有损坏条目,Python在这方面表现尚可。诸如此类。
关键在于:虽然Python未必是特定任务的首选,但对多数任务而言,它作为第二或第三选择完全可行。
所以你可以学Python。或者你学习
<最佳语言>和<其他语言>。若<其他语言>是Python,那么<最佳语言>是否真的比Python优秀到值得花时间学习?现在或许如此,但曾经他们需要招募数据科学人才时,可是从其他领域挖人呢。
你那句“Python不是优秀语言”就让我信服了
Python在任何领域都不算优秀语言。或许适合教学编程吧(不过结果就是培养出只会Python的人)。
听起来是技能问题
我认为这种期待——即数据科学代码本质上是自上而下编写以获取答案,将其绘制成图后便可继续生活——并非评估两种编程语言的有效视角。R语言确实是高效的统计专用领域语言,但若用它构建持久化软件则痛苦不堪。Python虽非完美,但我见过更少令人眼花缭乱的代码库——即便图表再华丽。
本文核心观点如下:
– 像 Python 这样的通用语言足以胜任数据科学,但并非为此专门设计。
– 像 R 这样专为数据科学设计的语言,在数据科学领域表现更优。
谁能想到呢?
发现这本质上是 R 语言与 Python 之争的文章,不禁有些失望——这在数据科学领域已是陈词滥调。从业二十余载,我曾坚定支持R阵营,如今却认为数据科学领域尚未出现真正优秀的语言。Julia曾让我寄予厚望,Clojure的数据生态也颇具吸引力,但面对Python的强势发展态势,我实在难以想象它会被取代。
Python无处不在。最近面试一批数据科学家时,仅一人掌握SQL,而所有候选人都使用Python。我敢说他们中根本无人听说过R语言。
SAS > R > Python。
SAS和R的应用主要局限于数据科学相关领域;而Python作为通用性更强的编程语言,接触者群体更为广泛。因此,具备Python经验的人才储备远超SAS/R——即便在本科/研究生课程中积极推广SAS的时期亦是如此。
作为数据科学与工程领域的招聘负责人,我对上述所有技术(及SQL等)均有丰富经验。如今招聘已能轻松跨越专业背景/学历限制,找到能即刻上手的优秀人才。
你抢先一步了。我理解SAS为何饱受诟病,但这往往源于人们根本不了解它的强大之处。
它曾是优秀的语言,但成本高昂得令人望而却步,加之学术界因诸多相同原因逐渐弃用,最终被免费替代品取代。
天啊。他们是资深数据科学家还是刚毕业的新人?竟不懂SQL实在令人费解(甚至有些可怕)。
无论资深数据科学家还是应届毕业生,在SQL实战经验方面都存在严重短板,这种现象由来已久。以拥有25年SAS经验的数据科学家为例,其中 许多人 精通DATAstep,却极少掌握通过PROC SQL高效查询数据的技巧——即便他们能借助SAS/ACCESS的直通模式提取数据。
他们通常采用极其简单的查询方式,随后通过DATAstep进行数据处理,最后才运行建模和/或报告PROC程序,而非将数据推送至上游,通过穿透机制采用原生数据库SQL进行更高效的数据提取。
早在2008/2009年,我通过将常规报告的全部代码重构为SQL穿透处理,成功节省了30小时以上的运行时间——而数据科学家原先的代码仅是从外部源提取数据后在DATAstep中进行处理。运行时间从30小时缩短至3分钟(Oracle后端),释放出整整一个全职员工的工时——从每周三次看守长时作业,变为每日多次处理。
所谓“适合数据科学的优秀语言”究竟意味着什么?
首先数据科学更像是给一袋猫贴的标签,而非由等大箱子装载的广阔领域。
SAS已加入讨论
正确,它只是我们现有工具中最优的选择
遗留Python代码良莠不齐。继承的R代码简直是噩梦。
我想指出的是,第一个企鹅示例里的Python代码到底是什么鬼?
看起来像状态不佳时的Perl,甚至更像自动生成的JavaScript。
为什么非要嵌套这么多层对象?
尝试Langgraph代理时被迫使用Python。
效果尚可,但TS/JS版本严重落后。React代理只需几行代码,同功能的JS/TS代码却要50多行。
宁可用陌生语言,也要维护几行代码而非50行。
Python算不上优秀语言
具体哪里不够优秀?
我同意Python没有特别突出的专长,但它几乎能胜任所有任务——这正是其卓越之处。
标题最后三个字完全可以省略啊 8-/
Python并非优秀语言
首先,其空格要求令人联想到1970年代Fortran的糟糕设计。
其次,这是与自身兼容性最差的语言。
Python美学设计欠佳。__init__(self)这种写法在2025年的语言中不可接受。Ruby本应是更优选择。语言设计中的粗糙感实属败笔。
2025年才有了@dataclass特性
Python在数值计算领域更是不堪入目:既不支持不同浮点类型,缺乏n维数组数据结构,运行效率更是极度低下。
但数值计算领域必须掌握它。这至少向我表明:只要缺陷能基本弥补,“足够好用”才是关键——数百万次集成、实例和文档的重要性,远超语言特性是否契合特定场景。
原生Python在数值计算领域毫无希望,因此几乎所有人都使用numpy来解决这些问题。当然,这需要额外安装包。但Python的优势在于能无缝集成这类增强核心功能的扩展包。另一个重要例子是pytorch。
注意文章中load_penguins()示例的处理逻辑:它在数据科学所有繁琐环节完成后才开始运行,并在下一个痛点出现前戛然而止。
这完全是理想化环境下的操作。
Python之所以成为数据科学实践中的优秀语言,是因为数据科学本质上还包含:
而Python及其生态系统恰恰擅长这些领域,同时在其他方面也表现不俗。
其他语言或许在某些领域表现卓越,但鲜少能全面兼顾。鉴于人类社会庞大、多元且持续革新,在这些领域位居次席终将赢得胜利。
因为无论你是谁,在任务X上体验不佳都会令人恼火。但若在任务Y和Z上遭遇最糟体验,你将痛不欲生。而任务X、Y、Z的定义因人而异。
你渴望高效完成工作,可一天只有24小时。
理解Python现象的诀窍,依然在于把握全局视野,而非局限于泡沫中的狭小角落。更不是你脑海中的理想世界。生活不是数学题——没有明确的前提条件,也没有优雅的答案。
这就像讨论PHP为何能在2000年称霸网络(无论代码多么混乱)、Windows为何长期被使用(尽管体验糟糕)、人们为何持续使用iPhone(尽管问题频出)等现象。其中蕴含的因素远超你日常接触的使用场景。人们的需求是你未曾设想过的。
所以这不是“语言战争开战”,而是“兄弟,多积累经验吧——去和会计师、非政府组织、政府部门及物流链合作,去中国、非洲和南美工作,从初创公司到学校再到企业,满足极客、艺术家和商人的需求,然后我们再谈”。
拒绝学习工具就怪工具有问题…Python在这方面毫无瑕疵。若厌恶模板化工作,加入自动化俱乐部让机器学习模型代劳,转而专注实质工作(或直接参与语言/库的改进)
但Python确实是数据科学的绝佳语言。正如英语谚语所言:实践出真知——它在数据科学领域的广泛应用,正是其卓越性的明证。
你会说并非所有成功的事物都优秀,这话没错。但Python的成功源于自然演进,而非广告宣传、事实垄断、政治操作、资金支持或先发优势。
不过确实存在一个非Python固有因素——来自numpy开发者的贡献。整个生态系统中存在这样一个统一的数值库:极易使用、运行迅捷且功能完备,这点极其关键。