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

Pandas合并IP归属地匹配场景DataFrame报MemoryError解决方案求助

IP区间关联内存溢出优化方案

原实现通过numpy广播生成全量布尔矩阵做匹配,12万条交易数据、13万条IP段的组合会产生15G以上的中间bool矩阵,直接触发内存溢出。以下是低内存优化方案:

方案1:使用pd.merge_asof(最推荐)

pandas内置的merge_asof专门针对有序区间匹配场景设计,全程不会生成超大中间矩阵,内存占用仅和原始表大小相关,执行效率最高。

import pandas as pd

# 前置步骤:确保所有IP字段已转换为整数数值类型,对两个表的关联键排序
df_ip_sorted = df_ip.sort_values("lower_bound_ip_address").reset_index(drop=True)
df_trans_sorted = df_transactions.sort_values("ip_address").reset_index(drop=True)

# 执行区间左匹配:匹配小于等于当前ip_address的最大lower_bound_ip_address
merged = pd.merge_asof(
    df_trans_sorted,
    df_ip_sorted,
    left_on="ip_address",
    right_on="lower_bound_ip_address",
    direction="backward"
)

# 过滤不符合上限要求的记录,得到最终匹配结果
final_df = merged[merged["ip_address"] <= merged["upper_bound_ip_address"]].reset_index(drop=True)

方案2:使用IntervalIndex映射

通过pandas的区间索引直接做值匹配,代码简洁,适合中等数据量场景:

# 生成包含上下限的区间索引,closed="both"表示区间同时包含首尾值
ip_interval = pd.IntervalIndex.from_arrays(
    df_ip["lower_bound_ip_address"], 
    df_ip["upper_bound_ip_address"], 
    closed="both"
)
# 将IP表的索引替换为上述区间索引
df_ip_interval = df_ip.set_index(ip_interval)

# 直接为交易表匹配国家,未匹配到的返回None
df_transactions["country"] = df_transactions["ip_address"].apply(
    lambda x: df_ip_interval.loc[x, "country"] if ip_interval.contains(x).any() else None
)

方案3:分批处理

如果不想修改原有逻辑,可以将交易表拆分为小批次逐批处理,控制单次中间矩阵的内存占用:

import numpy as np
import pandas as pd

batch_size = 10000 # 可根据自身内存调整,数值越小内存占用越低
res = []
bl = df_ip.lower_bound_ip_address.values
bh = df_ip.upper_bound_ip_address.values

for start in range(0, len(df_transactions), batch_size):
    # 取当前批次数据
    batch = df_transactions.iloc[start: start+batch_size]
    a = batch.ip_address.values
    # 原有匹配逻辑,仅作用于单批次,内存占用大幅降低
    idx_batch, idx_ip = np.where((a[:, None] >= bl) & (a[:, None] <= bh))
    batch_merged = pd.DataFrame(
        np.column_stack([batch.values[idx_batch], df_ip.values[idx_ip]]),
        columns=df_transactions.columns.append(df_ip.columns)
    )
    res.append(batch_merged)

# 合并所有批次结果
final_df = pd.concat(res, ignore_index=True)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:54:04