Skip to content

pandas 3.1 升级指南:解决 inplace 弃用的 Pandas4Warning、用 df.select() 和 pd.col()、read_csv 并行加速实测

更新于

pandas 3.1.0(2026 年 10 月 22 日发布)弃用了 drop、rename、sort_values 等 11 个方法的 inplace=True,新增 DataFrame.select() + pd.col() 表达式和 filter(cond=),并默认并行读取大 CSV。macOS 实测:72 MB 的 CSV 从 0.23 s 降到 0.02 s;附完整的 Pandas4Warning 方法列表、会悄悄关掉并行读取的 read_csv 参数,以及 Python 3.14 上的 NumPy 2.3.3 坑。

先说结论: pandas 3.1.0 已于 2026 年 10 月 22 日发布,11 月 4 日又发布了 3.1.1 修复版。直接升到 3.1.1:

pip install --upgrade "pandas>=3.1"
# or, in a uv project
uv add "pandas>=3.1"

升级之后会发生三件事:

  1. 代码会打印 Pandas4Warning 警告:drop、rename、reset_index、set_index、sort_values、dropna、drop_duplicates 等方法上的每一个 inplace=True 都会触发。修法很机械:把 df.drop(..., inplace=True) 改成 df = df.drop(...)。警告经常来自你用的某个库,而不是你自己的代码。
  2. pd.read_csv 读取大的本地文件快了很多。 我们测试的一个 72 MB 文件,在 pandas 3.0.1 上要 0.23 s,在 3.1 上只要 0.02 s。有几个常用参数会把这个加速关掉,下文会列出。
  3. 多了一套 Polars 风格的 API: df.select("a", pd.col("b") * 2) 和 df.filter(pd.col("a") > 1)。

如果你还在 pandas 2.x,升到 3.x(Copy-on-Write、默认字符串 dtype)才是更大的变化,应该从 pandas 3.0 迁移指南 (opens in a new tab) 开始。本文只讲 3.0 → 3.1,以及我们踩到的坑。

测试说明: 下文标注"实测"的内容,均于 2026 年 11 月 1 日在 Apple M4 Max(16 核,macOS)上完成,环境是新建的 uv 虚拟环境,CPython 3.14.2、pandas 3.1.0、NumPy 2.5.4、PyArrow 26.0.0。对比数据来自同一台机器上的 pandas 3.0.1 + NumPy 2.4.2,未安装 PyArrow。Windows、Linux、conda 和 Docker 上的行为来自官方文档,没有实测。2026 年 11 月 4 日,所有实测内容都在 pandas 3.1.1 上重跑了一遍,结果相同。

3.1 里你会实际碰到的变化

变化对你的影响怎么做
11 个方法的 inplace 被弃用(PDEP-8)每次调用都会发出 Pandas4Warning;pandas 4.0 将移除重新赋值:df = df.drop(...)
read_csv 并行读取,针对本地未压缩、≥ 5 MB 的文件单线程快 2–3 倍,再加上默认最多 6 个线程不用做什么,除非你传了 usecols、index_col、nrows 或文件句柄(见下文)
新增 DataFrame.select()(接受 pd.col() 表达式,后者 3.0 起就有)一次调用完成选列和计算列,Polars 风格可选;在方法链里很好用
filter(cond=...) 接受布尔掩码df.filter(pd.col("a") > 1) 按行筛选注意:按位置传入的布尔列表仍然按标签选择
要求 NumPy ≥ 2.0.2(Python 3.14 上 ≥ 2.3.3)NumPy 1.x 环境装不上 3.1先升级 NumPy,或固定 pandas<3.1
数值输入默认按微秒解析pd.to_timedelta([1], unit="s") 现在是 timedelta64[us],不是 [s]修复了 3.0 的一个取整 bug;需要特定精度时用 .as_unit()
read_csv 的 dtype="category" 会推断数值类别邮编和 ID 会丢掉前导零先按 str 读这些列

完整列表见 官方 What's new in 3.1.0 (opens in a new tab)。本文后面按顺序讲要动手做的事:安装、修警告、用新 API、加速 CSV 读取,以及检查那些不报错但会改变结果的行为变化。

第 1 步:安装 pandas 3.1

版本要求(实测)

pandas 3.1.0 为 CPython 3.11 到 3.15 提供 wheel(requires_python >= 3.11),PyPI 和 conda-forge 上都有。NumPy 的最低版本取决于你的 Python 版本:

PythonNumPy 最低版本
3.11 – 3.132.0.2
3.14 – 3.152.3.3

whatsnew 页面只提到 2.0.2。在 Python 3.14 上,wheel 元数据要求 2.3.3,解析器按这个执行。固定 NumPy 1.x 会直接失败:

  × No solution found when resolving dependencies:
  ╰─▶ Because pandas==3.1.1 depends on numpy>=2.3.3 and you require
      pandas==3.1.1, we can conclude that you require numpy>=2.3.3.
      And because you require numpy<2, we can conclude that your requirements
      are unsatisfiable.

如果某个依赖仍然固定 numpy<2,挡住升级的是那个依赖,不是 pandas。要么更新它,要么在它更新之前继续用 pandas<3.1。

升级(uv 实测)

请装 3.1.1,不要装 3.1.0:3.1.1 修复了一个回归问题,read_csv 和 to_csv 会把 pytest 的 tmpdir 这类路径对象当成已打开的文件句柄,可能报错或写出不完整的文件(What's new in 3.1.1 (opens in a new tab))。

# pip
pip install --upgrade "pandas>=3.1,<3.2"
 
# uv project
uv add "pandas>=3.1,<3.2"
 
# uv, throwaway environment to test first
uv venv p31 --python 3.14
uv pip install --python p31/bin/python "pandas==3.1.1" pyarrow
p31/bin/python -c "import pandas as pd; print(pd.__version__)"

conda-forge 上已经有 3.1.1(2026 年 11 月 4 日确认;conda install -c conda-forge "pandas>=3.1"),未实测。

如果还没装 PyArrow,顺手装上。pandas 3 在有 PyArrow 时会用它实现默认的字符串 dtype,engine="pyarrow" 的 CSV 读取器也需要它。

第 2 步:解决 inplace 的 Pandas4Warning

升级后,像这样的代码:

df.drop(columns=["rain"], inplace=True)

会打印:

Pandas4Warning: The inplace keyword in DataFrame.drop is deprecated and will be removed in a future version (PDEP-8).
See https://pandas.pydata.org/docs/dev/whatsnew/v3.1.0.html#deprecation-inplace for more details.

哪些方法受影响(实测)

这次弃用覆盖的是那些 inplace=True 从来没有真正原地修改过值的方法。对 dropna、sort_values 以及其他会重排行的方法来说,它底层一直是重新赋值;而 drop、rename 或 set_index 过去能省下的那次拷贝,在 pandas 3.0 引入 Copy-on-Write 之后本来也不会再发生。

方法3.1 中的 inplace修法
drop、rename、rename_axis已弃用df = df.drop(...)
reset_index、set_index已弃用df = df.reset_index()
sort_values、sort_index已弃用df = df.sort_values("col")
dropna、drop_duplicates已弃用df = df.dropna()
eval、query已弃用df = df.query("a > 1")
fillna、replace、where、mask、clip、interpolate保留(它们可以原地更新值)不用改

在我们的测试中,全部 11 个被弃用的方法在传 inplace=True 时都发出了警告;fillna 和 replace 没有,与文档一致。

替换是每处调用改一行:

# before
df.rename(columns={"temp": "temp_c"}, inplace=True)
df.sort_values("temp_c", inplace=True)
df.reset_index(drop=True, inplace=True)
 
# after (same cost, chains cleanly)
df = (
    df.rename(columns={"temp": "temp_c"})
      .sort_values("temp_c")
      .reset_index(drop=True)
)

找出代码库里的每一处调用(实测)

把警告临时变成错误跑一次,traceback 会直接指到那一行。python -W 不接受 pandas.errors.Pandas4Warning 这样的第三方类:它会打印 Invalid -W option ignored: invalid module name: 'pandas.errors',然后照常运行脚本。改为按消息文本匹配:

python -W "error:The inplace keyword:DeprecationWarning" your_script.py

如果想把所有 Pandas4Warning 都变成错误,而不只是 inplace 相关的:

python -c "import runpy, warnings, pandas as pd; warnings.simplefilter('error', pd.errors.Pandas4Warning); runpy.run_path('your_script.py', run_name='__main__')"

两种写法都会在第一处 inplace 调用处带着 traceback 退出。按消息过滤不会影响其他无关的弃用警告。

测试套件的情况不同:pytest 在 pandas 可以导入之后才应用 -W 过滤器,所以在那里可以直接写类名:

pytest -W error::pandas.errors.Pandas4Warning

Pandas4Warning 是 PandasDeprecationWarning 的子类,按任意一个过滤都可以。grep 也能找出大部分:

grep -rn "inplace=True" --include="*.py" --include="*.ipynb" .

警告来自某个库,而不是你的代码

这是新版本发布后前几周最常见的情况。2026 年 10 月 22 日到 11 月 1 日之间,GitHub 上新增了约 300 个提到 Pandas4Warning 的 issue 和 PR,以及约 3,500 个提到 "pandas 3.1" 的,涉及 yfinance(8 个文件里 29 处 inplace 调用,yfinance #3009 (opens in a new tab);已在 11 月 3 日发布的 yfinance 1.8.0 中修复)、FLAML、marimo、cuDF、darts 和 category_encoders 等项目。

这些你没法从自己的代码里修。可选方案,按优先顺序:

  1. 更新这个库。 很多库几天内就发布了修复。
  2. 只屏蔽这一类警告,等库跟上来,而不是屏蔽所有警告:
import warnings
import pandas as pd
 
warnings.filterwarnings("ignore", category=pd.errors.Pandas4Warning)
  1. 把 pandas<3.1 固定下来,只在运行那个无人维护的库的环境里这么做。不要永远固定在 pandas 3.0;inplace 关键字会在 4.0 移除,这个警告就是给你的过渡期。

3.1 里你可能碰到的其他弃用(除标注外均为实测)

现在会警告的写法替代写法
s.dt.dayofweek、.dayofyear、.daysinmonths.dt.day_of_week、.day_of_year、.days_in_month
对字符串列用 df.select_dtypes(include="object")(3.0 已经会警告;3.1 新增了 exclude="object")显式传 "str";在 pandas 3 里 "object" 不再表示"文本"
对 float 列用 s.fillna("missing")先转成共同的 dtype;未来版本会直接报错
对带时区的列用 ser.valuesser.array、ser.to_numpy(),或用 ser.dt.tz_convert(None).to_numpy() 保留旧的 UTC 数组
pd.infer_freq(idx) 返回 "D"将改为返回 offset 对象;用 .freqstr,或设置 future.infer_freq_returns_offset
read_parquet(engine="fastparquet")(文档)fastparquet 已退役;用默认的 PyArrow 引擎
pd.set_eng_float_format()(文档)pd.set_option("display.precision", n)

第 3 步:使用 df.select()、pd.col() 和 filter(cond=)

DataFrame.select() 和 filter(cond=) 是 3.1 里肉眼可见的新 API。pd.col() 本身在 pandas 3.0 就已出现,用于 assign() 和 .loc;到了 3.1,它自然成了这两个新方法的参数。用过 Polars 的话会觉得很熟悉。

select 一次调用完成选列和计算列(实测)

import pandas as pd
 
df = pd.DataFrame({
    "city": ["Tokyo", "Seoul", "Osaka"],
    "temp": [18.2, 15.1, 19.5],
    "rain": [12, 30, 8],
})
 
df.select("city", "temp")                         # same as df[["city", "temp"]]
df.select("city", temp_f=pd.col("temp") * 1.8 + 32)   # keyword names the new column
    city  temp_f
0  Tokyo   64.76
1  Seoul   59.18
2  Osaka   67.10

后面的参数可以引用同一次调用里前面刚创建的列,和 assign 一样:

df.select(temp_c=pd.col("temp"), temp_f=pd.col("temp_c") * 1.8 + 32)

pd.col("temp") 是一个 pandas.api.typing.Expression。它支持你在 Series 上会用的运算符和访问器,包括 .str 和 .round():

df.select(pd.col("city").str.upper(), pd.col("temp").round(0))

三个让我们绊了一下的地方(实测):

  • 没有 .alias()。 计算列要用关键字形式命名(temp_f=...)。pd.col("temp").alias("x") 本身构建时不会报错,但随后 df.select(...) 会失败,报 AttributeError: 'Series' object has no attribute 'alias'。
  • 归约成标量的表达式,比如 pd.col("temp").mean(),必须以关键字传入(mean_temp=pd.col("temp").mean()),结果会广播到每一行。按位置传入会抛 TypeError。
  • 列不存在时抛 KeyError,和 df[["nope"]] 一样。

filter(cond=) 用布尔掩码筛选行(实测)

DataFrame.filter 过去只能选标签(items=、like=、regex=)。3.1 开始它也接受掩码:

df.filter(cond=df["temp"] > 17)          # a boolean Series
df.filter(pd.col("temp") > 17)           # an expression, positional is fine
df.filter(lambda d: d["rain"] < 20)      # a callable

链式写法读起来像 Polars,但仍然是 pandas DataFrame:

(
    df.filter(pd.col("rain") < 20)
      .select("city", "temp")
      .sort_values("temp")
)

掩码里的缺失值默认按 False 处理;传 na=True 保留它们,或传 na="raise" 直接报错。

坑在这里: 按位置传入的普通布尔列表仍然走标签路径。在我们的测试中,df.filter([True, False, True]) 返回了一个零列的 DataFrame,并附带一条让我们改用 cond= 的 UserWarning。掩码是列表或数组时,一定要写 cond=。

Polars 与 pandas 3.1 对照

任务Polarspandas 3.1
选列df.select("a", "b")df.select("a", "b")
计算列df.select(pl.col("a") * 2)df.select(pd.col("a") * 2)
命名(pl.col("a") * 2).alias("a2")df.select(a2=pd.col("a") * 2)
筛选行df.filter(pl.col("a") > 1)df.filter(pd.col("a") > 1)
聚合df.select(pl.col("a").mean()) → 1 行df.select(m=pd.col("a").mean()) → 广播到每一行

pandas 并没有变成 Polars:select 背后没有惰性求值,也没有查询优化器。它只是让链式写法更易读、不用反复写 DataFrame 名字的语法。如果你在考虑要不要换引擎,Polars 和 pandas 的取舍需要单独比较,本文不展开。

第 4 步:用上更快的 read_csv,并知道什么会把它关掉

基准测试(实测)

一个文件:3,000,000 行 × 3 列(float、int、string),72.5 MB,未压缩,本地 SSD。三次取最优。

读取方式耗时相对 pandas 3.0.1
pandas 3.0.1,engine="c"0.233 s1x
pandas 3.1.0,mode.max_threads = 1(串行)0.089 s2.6x
pandas 3.1.0,2 线程0.049 s4.8x
pandas 3.1.0,4 线程0.025 s9.3x
pandas 3.1.0,默认(6 线程)0.018 s13x
pandas 3.1.0,engine="pyarrow"0.030 s7.8x

串行那一行和发布说明一致("快两到三倍");并行的几行是在此基础上再叠加。你的文件会不一样(字符串列越多解析越慢),但结果的形状才是重点:对于普通的本地文件,默认的 engine="c" 读取器现在比 PyArrow 还快。

触发条件(来自文档,上面的计时可以印证)

满足以下全部条件时,并行路径自动启用:

  • filepath_or_buffer 是本地、未压缩的文件路径
  • 使用默认的 C 引擎
  • 数据行总大小至少 5 MB
  • mode.max_threads 大于 1(默认为 CPU 数量,上限 6;进程被限制为单 CPU 时为 1)
  • 没有需要一次读完整个文件的选项:iterator、chunksize、nrows、usecols、index_col、parse_dates、列表或可调用对象形式的 skiprows、多行表头,或非 UTF-8 编码

其他情况都会回退到串行读取器,结果始终与串行读取完全一致。

我们测试中的实际表现(实测)

调用耗时并行?
pd.read_csv("big.csv")0.018 s是
pd.read_csv("big.csv", usecols=["a", "c"])0.079 s否
pd.read_csv("big.csv", index_col=0)0.091 s否
pd.read_csv("big.csv", nrows=1_000_000)0.032 s否(串行,只读了文件的三分之一)
pd.read_csv("big.csv", converters={"b": int})0.255 s否(比普通读取慢,但仍比 3.0 上的同一调用快)
pd.read_csv(open("big.csv", "rb"))0.091 s否(文件句柄,不是路径)
pd.read_csv(io.StringIO(text))0.131 s否
pd.read_csv("big.csv.gz")0.163 s否(压缩文件)
pd.concat(pd.read_csv("big.csv", chunksize=500_000))0.099 s否
pd.read_csv("big.csv", dtype={...})0.034 s是(显式 dtype 没问题)
pd.read_csv("big.csv", na_values=["z"])0.025 s是

两个实际影响:

  • usecols 现在可能让读取变慢,而不是变快。 多年来的建议是"传 usecols 跳过不需要的列"。在 3.1 上读 ≥ 5 MB 的本地文件时,我们测试中并行读完所有列再丢掉多余的列,比 usecols 快 4 倍。先测一下,再决定要不要保留老习惯。
  • 传路径,不要传句柄。 pd.read_csv("file.csv") 是并行的;pd.read_csv(open("file.csv")) 不是。那些把打开的文件对象而不是路径交给 pandas 的封装层会失去加速。

在已经并行的应用里把线程数调低

如果 pandas 运行在 Dask、Ray、multiprocessing 进程池,或已经占满所有核心的 Web worker 里,限制一下线程数,避免互相争抢:

import pandas as pd
 
with pd.option_context("mode.max_threads", 1):
    df = pd.read_csv("large.csv")
 
# or globally
pd.set_option("mode.max_threads", 2)

在 Docker 和 Kubernetes 里,上限跟随 cgroup 的 CPU 配额(来自文档,未实测),所以被限制为单 CPU 的容器会自动串行读取,你不需要做任何事。

第 5 步:检查不报错的行为变化

这些是最可能悄悄改变结果的变化。每一项都在 3.0.1 和 3.1.0 上复现过(实测)。

数值转 Timedelta 和 datetime 现在默认微秒精度

在 3.0 里,pd.to_timedelta([1], unit="s") 生成 timedelta64[s],算术运算保持这个精度。除法会被取整到整秒:

td = pd.to_timedelta([1], unit="s")
print(td / 3)
# pandas 3.0.1 → TimedeltaIndex(['0 days'], dtype='timedelta64[s]', freq=None)
# pandas 3.1.x → TimedeltaIndex(['0 days 00:00:00.333333'], dtype='timedelta64[us]', freq=None)

3.1 的修法是:无论你用什么 unit 转换,默认都用微秒。如果你的代码比较过 dtype,或依赖 [s] 精度,请显式调用 .as_unit("s")。Timestamp 和 to_datetime 接收数值输入时也做了同样的改变。

相关:Timedelta.total_seconds() 现在包含纳秒。pd.Timedelta(nanoseconds=1500).total_seconds() 返回 1.5e-06,而不是 1e-06。

read_csv 的 dtype="category" 会推断数值类别

from io import StringIO
data = "zip\n00501\n00501\n10001"
 
pd.read_csv(StringIO(data), dtype="category")["zip"].cat.categories.tolist()
# pandas 3.0.1 → ['00501', '10001']
# pandas 3.1.0 → [501, 10001]        leading zeros gone

C 引擎现在的行为和 PyArrow 引擎之前的行为一致。邮编、账号以及任何补零的标识符,先按 str 读进来再转换:

df = pd.read_csv("file.csv", dtype={"zip": "str"})
df["zip"] = df["zip"].astype("category")

以前静默通过、现在会报错的写法

  • pd.Timestamp(datetime(2020, 12, 31), hour=5) 在我们的测试中抛 ValueError;3.0 会静默忽略 hour。改为全部用关键字传入各个分量。
  • pd.to_timedelta("3:25:00 PM") 会报错;3.0 把它解析成三小时,并丢掉了 PM。
  • DataFrame 沿默认的 axis="columns" 与 category 类型的 Series 做算术和大小比较(例如 df + cat_series)现在会抛 TypeError,而不是对类别值进行运算;相等比较不变(文档,已复现)。
  • Index.values 和 Index.array 返回只读数组,之前通过它们修改索引的代码现在会明确报错,而不是悄悄破坏查找(文档)。

PyArrow 字符串上的正则(实测)

安装了 PyArrow 时,pandas 3.0 里 .str.replace、.str.count 等方法中的 \w、\d、\s、\b 只匹配 ASCII。3.1 恢复为匹配 Unicode,与 Python 的 re 和 pandas 2.x 一致。在 PyArrow 26.0.1 下,pd.Series(["héllo wörld", "naïve 東京"]).str.count(r"\w") 在 pandas 3.0.6 上返回 [8, 4],在 3.1.1 上返回 [10, 7]。如果你处理非英文文本,升到 3.0 后发现计数变少,这就是修复。3.1.1 还修复了 PyArrow 字符串上 \s 不匹配 \x0b 和 \x1c 的问题。

现在该不该升级?

你的情况建议
新项目,Python 3.11+升。直接从 3.1 开始,不写 inplace
3.0 上的脚本和 notebook升。用 -W "error:The inplace keyword:DeprecationWarning"(或 pytest -W error::pandas.errors.Pandas4Warning)跑一次,改掉那几行,用上更快的 CSV 读取
用 dtype="category" 加载补零 ID 的库或流水线升,但先加上 dtype={"id": "str"}
依赖 FLAML、darts 之类等它们发布 3.1 修复后再升(yfinance 已在 1.8.0 中修复),或先过滤掉 Pandas4Warning
还在 pandas 2.x先做 2 → 3 迁移(Copy-on-Write、字符串 dtype);3.1 在那之上只是小改动
还在 NumPy 1.x被挡住了。先升级 NumPy

在 Jupyter 里使用 pandas 3.1

notebook 本身没有变化。两点说明:

  • -W error 是命令行参数,对正在运行的内核不起作用。清理期间把 warnings.simplefilter("error", pd.errors.Pandas4Warning) 放在第一个单元格里,改完再删掉。
  • 并行 CSV 读取器不需要自由线程版 Python;标准解释器就能用。

大文件零点几秒就能加载之后,慢的环节就变成了看数据。PyGWalker (opens in a new tab) 0.5.0.1 在我们的测试中可以在 pandas 3.1 上运行(pyg.to_html(df) 渲染一个 50,000 行的 DataFrame 用了 0.23 s),所以在动手写 groupby 代码之前,先对刚加载的 DataFrame 拖拽着看一遍,是个合理的下一步。

常见问题排查

ResolutionImpossible / "requires numpy>=2.3.3" — 你在 Python 3.14 或 3.15 上,NumPy 被固定在旧版本。升级 NumPy 或放宽固定。Python 3.11–3.13 上的最低版本是 2.0.2。

site-packages 里冒出几百行 Pandas4Warning — 来自某个依赖,不是你的代码。更新它;如果还没有修复,先 warnings.filterwarnings("ignore", category=pd.errors.Pandas4Warning),并带着 traceback 去提 issue。

read_csv 没有变快 — 对照第 4 步的列表。常见原因是 usecols、index_col、压缩文件,或者传了文件对象而不是路径。另外确认 pd.get_option("mode.max_threads") 不是 1(默认是 None,表示"自动")。

df.filter([...]) 返回了零列 — 你按位置传了布尔列表。改用 df.filter(cond=[...])。

AttributeError: 'Series' object has no attribute 'alias' — pd.col 表达式没有可用的 alias;用 select 的关键字形式给列命名。

邮编丢了前导零 — dtype="category" 现在会推断成整数。先按 str 读。

Timedelta 的 dtype 从 [s] 变成了 [us] — 3.1 的预期行为。下游系统需要秒时用 .as_unit("s")。

常见问题

Pandas4Warning 是什么,怎么解决?

它是 pandas 3.1 针对将在 4.0 改变的行为发出的弃用警告,最常见的触发点是 drop、rename、reset_index、set_index、sort_values、dropna 和 drop_duplicates 上的 inplace=True。改为重新赋值:df = df.drop(columns=["a"])。运行 python -W "error:The inplace keyword:DeprecationWarning" your_script.py(测试套件用 pytest -W error::pandas.errors.Pandas4Warning),会在剩下的第一处调用停下并给出 traceback;改完再运行一次。

pandas 3.1 移除 inplace=True 了吗?

没有。3.1 里它仍然可用,只是会打印警告。移除计划在 pandas 4.0,而且只针对那些从未真正原地修改数据的方法。fillna、replace、where、mask、clip 和 interpolate 保留这个关键字。

read_csv 为什么更快了?我的为什么没变快?

C 引擎快了 2–3 倍,大的本地文件默认并行读取。如果没看到变化,多半是传了 usecols、index_col、nrows、chunksize、压缩文件,或者打开的文件对象。见第 4 步的表格。

df.select() 和 Polars 的 select 一样吗?

语法刻意做得相似,但 pandas 是立即求值,没有查询优化器。用它来写易读的链式调用,不要指望它带来性能提升。

pandas 3.1 支持 Python 3.15 吗?

支持。官方为 CPython 3.11 到 3.15 发布了 wheel。在 3.14 和 3.15 上需要 NumPy 2.3.3 或更高版本。Python 这一侧的升级可以看我们的 Python 3.15 升级指南。

相关指南