社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

“Python 不是数据科学的最佳语言!”

AI思想会 • 9 月前 • 363 次点击  
【前言】AI 正以前所未有的速度发展,新的机遇不断涌现,如果你希望:与技术专家、产品经理和创业者深度交流,一起探索 AI如何改变各行各业。欢迎在文末扫二维码,加入「AI思想会」交流群,和一群志同道合的伙伴共同学习、思考、创造!

我已经准备好踩进语言之争这趟浑水了。但我先说一句最重要的:用你最熟的工具。比如你熟悉 Python?那就用 Python。再补充一句:做哪件事最合适用哪个工具就用哪个工具。如果刚好还是 Python,那也没问题。

还有就是,如果你本来就天天用某个工具,顺手拿它来干点别的活,也完全正常。你一天到晚拿锤子敲钉子,用它开瓶啤酒、挠挠背,也都说得过去。同样地,你整天写 Python,用它顺带做做混合线性模型,也没毛病。

如果你用得顺手,那继续用就行。但如果你越用越觉得别扭、感觉一些事情明明不该这么难,那这篇文章可能就是给你看的。

首先,我提出一个观点——大家对“Python 是数据科学语言”这件事过度依赖了。它的局限性其实相当明显。有许多数据科学任务,我宁可用 R 完成,也不愿用 Python。

之所以 Python 在数据科学领域如此普及,我认为更多是历史偶然,加上一种“各方面都还行”的通用性,而不是它在数据科学上有某种天生优势。

与此同时,我认为 Python 在深度学习上确实表现不错。PyTorch 之所以成为行业标准是有理由的。这里我谈的数据科学,并不包括深度学习,而是指其他那些工作:数据清洗、探索性分析、可视化、统计建模等等。

正如开头提到的,如果你本来就有充分理由每天都在用 Python(比如训练 AI 模型),那么顺便用它把剩下的事情一起做完也可以。我自己在教授深度学习课程时就是这么做的。但这并不能抵消我在 Python 世界里做数据分析时常常感到的笨拙与不便。

图片


图片

来自一线的观察

我先谈谈自己的亲身经历,不做任何原因分析。我带领计算生物实验室已经二十多年了,期间合作过大约三十位能力很强的研究生和博士后。实验室的规则是:每个人可以自由选择任何想用的编程语言和工具,我从不干预。

结果往往是,大多数人会选择 Python。

下面是我经常遇到的情况:一位学生来办公室向我展示一些结果。我说:“这很好,你能不能把图换一种方式快速画一下?”或者“能不能快速算一个我刚想到的量,并画出来看看?”诸如此类的需求。通常这些都是我知道在 R 里几分钟就能搞定的任务,比如把箱线图改成小提琴图、把折线图改成热力图、把直方图换成密度估计、把原始值换成排序值再计算等等。

几乎毫无例外,使用 Python 的学生总会回答:“这要花点时间,我得回去研究一下,弄好再告诉你。”

我要强调的是:这些学生都非常强。问题并不是他们不懂工具,而是工具本身似乎就比较笨拙,让我以为是“非常简单的请求”,却经常变得一点也不简单。

无论原因是什么,我都不得不得出一个结论:Python 在数据分析上的某些基础环节出现了结构性问题。可能是语言本身的问题,也可能是库生态的问题,或两者共同作用,但结果是真实存在的,而且我长期都能看到类似情况。

事实上,我再举一个例子,以避免你认为“这是学生水平问题”。

去年秋天,我和一位资深的数据科学家一起教授生物学的 AI 课程。他所有工作都用 Python,对 NumPy、pandas、matplotlib 都熟得不能再熟。在课上,他负责带学生做 Python 练习,我负责讲理论。这让我可以观察到一位 Python 专家如何现场解决各种数据分析问题。

我的反应往往是:“为什么要写得这么复杂?”许多我认为用 R 几行就能写出的东西,在 Python 里却变得又长又绕。我自己要是不花大量时间重新训练大脑、适应完全不同的编程思维,就根本写不出那些代码。这种陌生感并不是“陌生但优雅”,而是“陌生、怪异、且繁琐”。

而我很确定原因不在于同事,他非常厉害。真正的问题,似乎就在这些工具的底层设计上。


图片

什么才是适合数据科学的语言?

退一步讲,选择数据科学语言时有一些基本考量。这里说的数据科学,是指剖析和总结数据、寻找模式、拟合模型、绘制可视化——也就是科研人员在日常数据分析中会做的所有工作。这与数据工程或应用开发并不相同。

数据科学高度依赖交互式探索,需要大量快速试验性的分析。因此,适合数据科学的语言必须支持解释执行,并能在交互式 Shell 或 Notebook 中使用。性能反而是次要的。当你做一个线性回归时,你根本不会在意是 50ms 还是 500ms;你关心的是:能不能立刻打开 Shell,写几行代码,几分钟内得到结果,而不是新建工程、写一堆模板代码、取悦编译器,还要花比运行更久的时间等待编译。

既然交互性和低启动成本是必须,那候选自然落在 Python、R、Matlab、Mathematica 这类脚本或数据科学语言上。也包括 Julia,但说实话我对 Julia 了解不足,不好评价。它可能非常优秀,但我也看到不少深度用户对它有所保留。本文就不展开。Matlab、Mathematica 之类的商业语言,以及缺乏生态的 Octave 也先放一边。现实选择就是 R 和 Python。

继续之前我想补充一下关于性能的看法。性能通常要以牺牲语言其他特性为代价:程序员额外负担(如 Rust)、更高的隐蔽 bug 风险(如 C),或两者皆有。在数据科学里,高 bug 风险不可接受,而程序员便利性远比极致性能重要。电脑足够快,而思考会痛。我宁愿少费心力告诉电脑该做什么,多等一会儿。有真正性能瓶颈时,我完全可以在明确需求后把关键路径重写成 Rust。


图片

把“逻辑”与“搬运工作”分开

不让分析变得更困难的关键,就是把“分析逻辑”与“实现细节”分离。我希望能用概念层面的描述来写分析代码:数据要怎么处理、目标是什么;而不想被迫去操心底层细节,比如数据类型、数字索引、循环、手动拆装数据表等等。

只要我开始管这些事,那多半是在被“繁琐的机械劳动”拖累。

举个例子,来看 Palmer 群岛的企鹅数据集。里面有三种企鹅分布在三座岛上。假设我要计算“岛 × 物种”两个维度下的体重均值和标准差,并排除体重缺失的记录。

理想的数据科学语言应该能让我以接近自然语言的方式完成这个任务,用的代码量与我刚用英语描述的句子词汇量差不多才算优秀。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)  )

再来看等价的 Python 代码,使用 pandas 完成相同任务:

import pandas as pdfrom palmerpenguins import load_penguinspenguins = 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 里有多少引号和括号),但差别不算大。

两者的流程也一致:取 penguins 数据集、去掉体重缺失的记录、按“物种 × 岛屿”分组,然后分别计算均值和标准差。

对比一下只用 Python 基础语法、完全不依赖数据处理库时的等价版本:

from palmerpenguins import load_penguinsimport mathpenguins = load_penguins()# Convert DataFrame to list of dictionariespenguins_list = penguins.to_dict('records')# Filter out rows where body_mass_g is missingfiltered = [row for row in penguins_list if not math.isnan(row['body_mass_g'])]# Group by species and islandgroups = {}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 groupresults = []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 pandasresults.sort(key=lambda x: (x['species'], x['island']))# Print resultsfor 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")

这段代码明显长得多,里面到处是循环,还得把数据集拆开再重新拼回去。不管你喜欢哪种语言,应该都能看出来:不用管这些琐碎步骤、直接表达你要做什么的版本,比被一堆杂事拖住的版本好太多了。

简单来说,我觉得 Python 代码之所以动不动就变成“苦力活”,是因为无论你多想保持高层抽象、写得清爽一点,语言本身或者它的库,总会出来添乱,让你不得不去处理那些底层细节。

(👇 长按识别二维码)
图片
转自:CSDN

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/189683