2015-05-07 4 views
5

Ich rufe eine Python-Funktion, um "T-Test" aus meinem C++ - Code zu berechnen. Der Funktionsaufruf wird wie folgt vorgenommen:Python Runtime Fehler beim Ausführen von T-Test

#include <iostream> 
#include "Python.h" 
#include "/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h" 

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 

int main(int argc, char** argv) 
{ 
    Py_Initialize(); 

    PyRun_SimpleString("import sys"); 
    PyRun_SimpleString("sys.path.append(\"PATH_TO_MOD\")"); 
    PyObject *pName = PyString_FromString("tmpPyth"); 
    PyObject *pModule = PyImport_Import(pName); 


    double arr[] ={9.74219, 10.2226, 8.7469, 8.69791, 9.96442, 9.96472, 9.37913, 9.75004}; 
    double arr1[] ={9.74219, 10.2226, 8.7469, 8.69791, 9.96442, 9.96472, 9.37913, 9.75004}; 

    PyObject *lst = PyList_New(8); 
    PyObject *lst1 = PyList_New(8); 
    // if (!lst) 
    //  return NULL; 
    for (int i = 0; i < 8; i++) { 
     PyObject *num = PyFloat_FromDouble(arr[i]); 
     PyObject *num1 = PyFloat_FromDouble(arr1[i]); 
     PyList_SET_ITEM(lst, i, num); 
     PyList_SET_ITEM(lst1, i, num1); 
    } 

    PyObject *pArgs = PyTuple_New(2); 
    PyTuple_SetItem(pArgs, 0, lst); 
    PyTuple_SetItem(pArgs, 1, lst1); 

    if (pModule != NULL) { 
     PyObject *pFunc = PyObject_GetAttrString(pModule, "blah"); 

     if(pFunc != NULL){ 
      PyObject_CallObject(pFunc, pArgs); 
     } 
    } 
    else 
     std::cout << "Module path provided may be wrong. Module not found.\n\n"; 
    return 0; 
} 

Und mein Python-Modul ist wie folgt definiert:

import numpy 
import scipy 
import matplotlib 

from scipy import stats 
def blah(baseline, follow_up): 
    paired_sample = stats.ttest_rel(baseline , follow_up) 
    print "The t-statistic is %.3f and the p-value is %.3f." % paired_sample 

Jetzt, wenn ich versuche, dies zu laufen bekomme ich die folgende Laufzeitausnahme:

/usr/local/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/stats/stats.py:3458: RuntimeWarning: invalid value encountered in divide 
    t = np.divide(dm, denom) 

Aber wenn ich explizit eine Liste definiere und versuche, die "t-test" -Funktion auszuführen, läuft sie gut. Die Lauffunktionsdefinition lautet wie folgt:

import numpy 
import scipy 
import matplotlib 

from scipy import stats 

    def blah(): 
     baseline = [9.74219, 10.2226, 8.7469, 8.69791, 9.96442, 9.96472, 9.37913, 9.75004] 
     follow_up = [9.94227,9.46763,8.53081,9.43679,9.97695,10.4285,10.159,8.86134] 
     paired_sample = stats.ttest_rel(baseline , follow_up) 
     print "The t-statistic is %.3f and the p-value is %.3f." % paired_sample 

Ich gehe davon aus, dass ich einige Fehler mache die Listen bei der Festlegung auf den Python-Skript übergeben werden kann aber nicht herausfinden, was. Jede Hilfe wäre willkommen.

+3

Es gibt nichts, das mich beim Lesen Ihrer Beschreibung springt, so dass es gut aussieht. Nur aus Neugier, rufen Sie 'blah()' und der Fehler ist in 'numpy.stats()', was sind die Werte, die in 'blah()' ankommen? Verwenden Sie 'print repr (baseline)' und 'print repr (follow_up)', um ihre Darstellungen auszugeben. Trotzdem, warum benutzt du immer noch Python 2? Numpy zumindest ist auch in aktuellen Pythons verfügbar. –

+0

Hmm, vielleicht eine dumme Frage, aber haben Sie darüber nachgedacht, die bereits existierenden [t-Tests von scipy] zu verwenden (http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.ttest_ind.html)) anstatt sie erneut zu implementieren? – mtzl

Antwort

0

arr1 in Ihrem C++ - Code ist identisch mit arr, daher die Division durch Null. Da baseline und follow_up in Ihrem Python-Code unterschiedlich sind, erhalten Sie keinen Fehler.

Bei größeren Arrays sollten Sie sie nicht über Python-Listen marshalieren, sondern stattdessen die Arrays direkt an Python senden. Ich habe den Code oben geändert, dies zu tun:

-- pyfromc.cc -- 
#include <iostream> 
#include <Python.h> 

int main(int argc, char** argv) 
{ 
    Py_Initialize(); 

    PyRun_SimpleString("import sys; sys.path.append('.')"); 
    // PyRun_SimpleString("print '\\n'.join(sys.path)"); 
    PyObject *pName = PyString_FromString("ttest"); 
    PyObject *pModule = PyImport_Import(pName); 

    double arr[] ={9.74219, 10.2226, 8.7469, 8.69791, 9.96442, 9.96472, 9.37913, 9.75004}; 
    double arr1[] ={9.94227,9.46763,8.53081,9.43679,9.97695,10.4285,10.159,8.86134}; 

    PyObject *pArgs = PyTuple_New(3); 
    PyTuple_SetItem(pArgs, 0, PyLong_FromLong(8)); 
    PyTuple_SetItem(pArgs, 1, PyLong_FromVoidPtr(arr)); 
    PyTuple_SetItem(pArgs, 2, PyLong_FromVoidPtr(arr1)); 

    if (pModule != NULL) { 
     PyObject *pFunc = PyObject_GetAttrString(pModule, "blahptr"); 

     if(pFunc != NULL){ 
      PyObject_CallObject(pFunc, pArgs); 
     } 
    } 
    else 
     std::cout << "Module path provided may be wrong. Module not found.\n\n"; 
    return 0; 
} 

und auf der Python-Seite:

-- ttest.py -- 
from ctypes import POINTER, c_double, cast 
c_double_p = POINTER(c_double) 

import numpy as np 
from scipy import stats 

def blahptr(n, baseline_ptr, follow_up_ptr): 
    baseline = np.ctypeslib.as_array(cast(baseline_ptr, c_double_p), shape=(n,)) 
    follow_up = np.ctypeslib.as_array(cast(follow_up_ptr, c_double_p), shape=(n,)) 
    return blah(baseline, follow_up) 

def blah(baseline, follow_up): 
    paired_sample = stats.ttest_rel(baseline , follow_up) 
    print "The t-statistic is %.3f and the p-value is %.3f." % paired_sample 
    return paired_sample 

Um den Code auf Mac OS XI verwendet die folgenden kompilieren und ausführen:

$ PYENV=/path/to/python/env 
$ c++ pyfromc.cc -I$PYENV/include/python2.7 -L$PYENV/lib -lpython2.7  
$ PYTHONHOME=$PYENV DYLD_LIBRARY_PATH=$PYENV/lib ./a.out 
The t-statistic is -0.187 and the p-value is 0.857. 

Durch Festlegen der Umgebungsvariablen in derselben Zeile wie die ausführbare Datei legt der Bash-Interpreter sie nur für die Dauer des Befehls und nicht für andere Befehle fest.

Verwandte Themen