You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas弃用lookup()后向量化交叉表查表的替代方案

Pandas 弃用lookup()方法的向量化替代方案

Pandas 旧版的lookup()方法已被标记为弃用,官方文档给出的几个原生替代方案均存在适配问题:loc()默认不支持逐行批量向量化匹配、melt()实现逻辑冗余繁琐、factorize()无法匹配当前使用场景,需要找到和原方法效果完全一致、支持向量化的高性能长期兼容实现。

问题场景

涉及两类核心数据表:

  • 基础明细表df为两列结构,分别存储坐标值x、y,构造示例代码如下:
import random
import pandas as pd
k = 20
y = random.choices(range(1,4),k=k)
x = random.choices(range(1,7),k=k)
tuples = list(zip(x,y))
df = pd.DataFrame(tuples, columns=["x", "y"])
  • 交叉表格式的查询表,以一致性表Cij为例,行索引为y取值,列名为x取值,表内存储对应坐标的匹配值,结构示例如下:
Concordance table (Cij):
x     1     2     3    4     5     6  RTotal
y                                           
1   16     15    13  NaN     5   NaN     108
2   NaN    12   NaN   15   NaN   NaN      87
3   NaN   NaN     6  NaN    13    14     121

核心需求:基于df中每一行的(x,y)值对,在Cij中批量匹配对应值,为df新增Crc列。原lookup()实现代码非常简洁:

df["Crc"] = Cij.lookup(df["y"],df["x"])

补充约束与可复现代码

  • 性能约束:交叉表Cij的规模始终很小,填充Cij时使用双层循环是可接受的;但基础表df的数据量可能非常大,查找操作必须使用向量化实现,不接受逐行循环的低效方案。
  • 可直接运行的复现代码如下:
data = [[1,1],[1,1],[1,2],[1,2],[1,2],[1,3],[1,3],[1,5],[2,2],[2,4],[2,4],[2,4],[2,4],[2,4],[3,3],[3,3],[3,5],[3,5],[3,5],[3,6],[3,6],[3,6],[3,6],[3,6]]
df = pd.DataFrame(data, columns=["y", "x"])

# 生成交叉表基础结构
ct_a = pd.crosstab(df["y"], df["x"])
Cij = pd.DataFrame([], index=ct_a.index, columns=ct_a.columns) # 同结构查询表之一

# 逐行逐列填充Cij值
for i in range(ct_a.shape[0]):           
  for j in range(ct_a.shape[1]):
    if ct_a.iloc[i,j] != 0:
      Cij.iloc[i,j]= ct_a.iloc[i+1:,j+1:].sum().sum()+ct_a.iloc[:i,:j].sum().sum()

# 原弃用方法实现的向量化查找,需要替换为长期兼容的实现
df["Crc"] = Cij.lookup(df["y"],df["x"])

推荐实现方案

官方推荐的高性能向量化替代方案基于NumPy高级索引实现,性能和原lookup()完全一致,无冗余逻辑,代码简洁度接近原方法:

# 将行、列标签转换为对应数组位置索引,通过NumPy索引批量取值
df["Crc"] = Cij.to_numpy()[Cij.index.get_indexer(df["y"]), Cij.columns.get_indexer(df["x"])]

方案说明

  • 实现完全向量化,即使df达到百万行级别也能毫秒级完成计算,性能和原lookup()方法无差异
  • 逻辑和原lookup()完全对齐:按传入的行标签序列、列标签序列逐行匹配对应位置的值,不存在结果偏差
  • 不需要对表做变形、长宽表转换等冗余操作,代码维护成本低
  • 对NaN值的处理和原方法完全一致,无对应有效值的位置会自动返回NaN,和原方法输出结果100%匹配

注意:不要直接使用loc[df['y'], df['x']]实现,该写法会生成笛卡尔积结果,不符合逐行匹配的预期。Pandas 2.0+版本也可以直接使用Cij.reindex(index=df['y'], columns=df['x'])配合对角线取值,但NumPy索引方案的兼容性覆盖所有仍在维护的Pandas版本。


内容的提问来源于stack exchange,提问作者Jakob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:12:15