对熊猫系列应用功能时结果不正确

时间:2018-10-19 13:19:00

标签: python pandas cython

当我尝试将两个版本的函数(纯python vs cython)应用于pandas系列时,会获得两个不同的结果

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
                .setSmallIcon(R.drawable.changer_ico)
                .setContentTitle(context.getString(R.string.service_ready))
                .setContentIntent(pendingIntent)
                .addAction(R.drawable.ic_key_black_24dp, context.getString(R.string.turn_on), pendingIntent)
                .setAutoCancel(true);

        Notification notification = notificationBuilder.build();
        NotificationChannel channel = new NotificationChannel("1903",
                context.getString(R.string.user_notify), NotificationManager.IMPORTANCE_DEFAULT);
        notificationManager.createNotificationChannel(channel);
        notificationManager.notify(1903, notification);

结果是

import numpy as np
import pandas as pd
from libc.math cimport lround

def py_func(n):
    return round(13 * n / 37)

cdef int cy_func(int n):
    return lround(13 * n / 37)

arr = np.arange(1000, 12000, 2000)

series = pd.Series(arr)
print("Original series:")
print(series)

series1 = series.apply(py_func)
series2 = series.apply(cy_func)

print("\nApplied with python function:")
print(series1)

print("\nApplied with cython function:")
print(series2)

我们可以看到,在应用python函数时,我们在最后三个数字中获得了错误的结果。 cython函数产生正确的结果。

为什么python函数会产生不正确的结果?以及如何解决?

更新

以上结果是在Windows 10 64位系统上获得的。但是,当我在同一台计算机(使用WSL)上尝试使用Ubuntu 18.04 64位时,两个系列都具有正确的结果。在这两种情况下,我都有Original series: 0 1000 1 3000 2 5000 3 7000 4 9000 5 11000 dtype: int32 Applied with python function: 0 351 1 1054 2 1757 3 688 4 1391 5 322 dtype: int64 Applied with cython function: 0 351 1 1054 2 1757 3 2459 4 3162 5 3865 dtype: int64 ,并且也经过了Cython==0.29, numpy==1.15.2, pandas==0.23.4的测试。

结果还有另一个差异:在Windows 10中,原始系列的Cython==0.28.5, numpy==1.14.5, pandas==0.23.3dtype,而在Ubuntu 18.04上的int32dtype。在两个操作系统中,两个结果系列的int64均为dtype

1 个答案:

答案 0 :(得分:1)

使用MinGW时,未定义MS_WIN64,它用于定义SIZEOF_VOID_P,具体如下pyconfig.h

#if defined(MS_WIN64)
...
#   define SIZEOF_VOID_P 8
...
#elif defined(MS_WIN32)
...
#   define SIZEOF_VOID_P 4
...
#endif
然后在SIZEOF_VOID_P中使用

pyport.h

#ifndef PYLONG_BITS_IN_DIGIT
#if SIZEOF_VOID_P >= 8
#define PYLONG_BITS_IN_DIGIT 30
#else
#define PYLONG_BITS_IN_DIGIT 15
#endif
#endif

解决方案是在使用MinGW进行编译时传递-DMS_WIN64

相关的Python ticketdiscussion on cython-users group