scipy.stats的beta函数替代逆计算

3 投票
1 回答
1438 浏览
提问于 2025-04-18 11:11

我发现了scipy.stats中beta.ppf函数的一个bug。这个问题已经被确认,并在他们的缺陷报告系统中标记为缺陷。

不过,现在我需要计算一个beta分布的置信区间,所以我需要这个beta函数的反函数。由于我不能依赖当前版本的beta.ppf,我需要在Python中找到一个替代方案。最好是我不想自己实现这个函数。

有没有人知道可以替代scipy.stats中beta.ppf函数的其他函数?

1 个回答

1

好吧,我找到了一种解决办法,使用了C++的boost库,这个库里有一个beta分布的实现。要使用这个库,你需要先安装boost库并进行编译。之后,你就可以用下面的代码来使用它:

betainv.cpp

#include <boost/python.hpp>
#include <boost/math/distributions/beta.hpp>

using namespace boost::python;

class betainvClass {
    public: double betainv(double p, double a, double b);
};

double betainvClass::betainv(double p, double a, double b) { 
    return boost::math::ibeta_inv(a, b, p);
}

// Expose classes and methods to Python
BOOST_PYTHON_MODULE(betainv) {
    class_<betainvClass> ("create_betainv_instance")
        .def("betainv", &betainvClass::betainv)
    ;
}

Makefile:

TARGET = betainv
PYTHON_INC = /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/include/python2.7
PYTHON_LIB = /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config
BOOST_INC = /usr/local/include
BOOST_LIB = /usr/local/lib

$(TARGET).so: $(TARGET).o
    g++ -shared -Wl \
    $(TARGET).o -L$(BOOST_LIB) -lboost_python \
    -L$(PYTHON_LIB) -lpython2.7 \
    -o $(TARGET).so

$(TARGET).o: $(TARGET).cpp
    g++ -I$(PYTHON_INC) -I$(BOOST_INC) -c $(TARGET).cpp

clean:
    rm -f *.o *.a *.so *~ core

Python示例文件:

import betainv

beta = betainv.create_betainv_instance()
print "0.25, 0.0342, 170 -> " + str(beta.betainv(0.25, 0.0342, 170))
print "0.25, 0.0342, 171 -> " + str(beta.betainv(0.25, 0.0342, 171))
print "0.25, 0.0342, 172 -> " + str(beta.betainv(0.25, 0.0342, 172))

顺便说一下,我做了个速度测试,运行这个方法1000次。第一次用scipy,第二次用我的boost实现。结果是这样的,单位是毫秒:

required time scipy = 295.145019531
required time c++   = 7.68383789062

boost的C++实现大约快了42倍。

撰写回答