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

PySpark DataFrame调用erfinv函数报scipy缺失,求替代实现方案

问题复现

在CDSW环境中运行如下Spark代码:

df = spark.createDataFrame([
    (1, 0.008),
    (2, -1.23),
    (3, 4.56),
], ['id', 'value'])

def normal_cdf(x):
    val = (math.sqrt(2) * erfinv(x*2-1)) 
    return float(val)
  
my_udf1 = udf(normal_cdf)
#my_udf1 = udf(normal_cdf,T.DoubleType()) for returning double

df1 = df.withColumn('prob', my_udf1(F.col('value')))
df1.show()

执行后报错根因为:ModuleNotFoundError: No module named 'scipy'
但单独运行如下代码可以正常执行:

n=math.sqrt(2)*erfinv(2*0.008-1)
print(n)

当前环境无权限安装或升级第三方依赖,需要无需额外依赖的erfinv计算方案。

问题根因

你本地Driver节点的Python环境已经导入了scipy的erfinv函数,所以单独运行代码正常。但Spark UDF会被分发到Executor节点执行,Executor节点的Python环境没有安装scipy,因此触发依赖报错。

解决方案

方案1:使用Spark内置函数(最优)

Spark 3.0及以上版本自带probit内置函数,逻辑完全等价于你需要实现的√2 * erfinv(2p-1),也就是标准正态分布的分位数函数,无需自定义UDF,完全避免依赖问题,同时执行性能远高于Python UDF。
实现代码如下:

from pyspark.sql import functions as F

df1 = df.withColumn('prob', F.probit(F.col('value')))
df1.show()

方案2:手动实现erfinv近似算法(兼容低版本Spark)

如果你的Spark版本低于3.0没有内置probit函数,可以使用精度足够的erfinv近似展开实现,仅依赖Python标准库math,无需任何第三方包:

import math
from pyspark.sql import functions as F
from pyspark.sql import types as T

def erfinv_approx(x):
    # 近似算法精度可达1e-4,满足绝大多数业务场景使用
    a = 0.147
    if abs(x) > 1:
        return float('nan')
    elif abs(x) == 1:
        return float('inf') * x
    ln1mx2 = math.log(1 - x**2)
    part1 = 2/(math.pi * a) + ln1mx2 / 2
    part2 = ln1mx2 / a
    return math.copysign(math.sqrt(math.sqrt(part1**2 - part2) - part1), x)

def normal_cdf(x):
    val = math.sqrt(2) * erfinv_approx(x * 2 - 1)
    return float(val)

my_udf1 = F.udf(normal_cdf, T.DoubleType())
df1 = df.withColumn('prob', my_udf1(F.col('value')))
df1.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:09:02