首页 > 解决方案 > TypeError: 无法根据 interp_func(x, xp, fp, left, right) 的规则“安全”将数组数据从 dtype('O') 转换为 dtype('float64')

问题描述

我有以下功能:

def interpolate_values(A):
    ''' fills values between pairs of events'''
    if type(A) ==list :
        A= np.array(A)
    ok = ~pd.isna(A)
    xp = ok.nonzero()[0]
    fp = A[~pd.isna(A)]
    x  = pd.isna(A).nonzero()[0]
    A[pd.isna(A)] = np.interp(x, xp, fp)
    A = [round(i) for i in A]
    return A

产生以下错误:

TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

指向线:

A[pd.isna(A)] = np.interp(x, xp, fp)

A 从以下函数传递:

def generate_appliance_powerseries(appliance_pairs,DelP):
    ''' generates full power series of appliances'''
    print ("3 of 6> generates full power series of appliances")
    appliance_signatures = OrderedDict()
    power_series = OrderedDict()
    ctlf = OrderedDict()
    for i in range(len(appliance_pairs)):
        events = appliance_pairs[i]
        timeseq= []
        powerseq  = []
        for event in events:
            start= event[0]
            end = event[1]
            duration = end - start
            instance = []
            instance.append([DelP[start]])
            temp= np.repeat(np.nan,duration-1).tolist()
            instance.append(temp)
            instance.append([abs(DelP[end])])
            final = [j for sub in instance for j in sub]
            timeval = range(start,end+1,1)
            #print (event)
            powerval = interpolate_values(final) if sum(pd.isna(final)) else final
            timeseq.append(timeval)
            powerseq.append(powerval)
        powerseq =  [j for sub in powerseq for j in sub]
        timeseq =  [j for sub in timeseq for j in sub]
        power_series[i] = pd.DataFrame({'timestamp':timeseq,'power':powerseq})
        appliance_signatures[i] = pd.DataFrame(powerseq)

    return power_series, appliance_signatures

有人能知道是什么问题吗?如果需要任何其他信息,请告诉我。

标签: pythonpython-3.xpandasnumpy

解决方案


在简单的浮点数组上运行您的函数:

In [265]: import pandas as pd
In [266]: A = np.arange(10.)
In [267]: A[1::2]=np.nan
In [268]: A
Out[268]: array([ 0., nan,  2., nan,  4., nan,  6., nan,  8., nan])
In [269]: def interpolate_values(A):
     ...:     ''' fills values between pairs of events'''
     ...:     if type(A) ==list :
     ...:         A= np.array(A)
     ...:     ok = ~pd.isna(A)
     ...:     xp = ok.nonzero()[0]
     ...:     fp = A[~pd.isna(A)]
     ...:     x  = pd.isna(A).nonzero()[0]
     ...:     A[pd.isna(A)] = np.interp(x, xp, fp)
     ...:     A = [round(i) for i in A]
     ...:     return A
     ...: 
In [270]: interpolate_values(A)
Out[270]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 8]

但是,如果我更改Aobjectdtype (如果从数据框派生的可能情况):

In [271]: interpolate_values(A.astype(object))
Traceback (most recent call last):
  File "<ipython-input-271-0ca27d4b7eab>", line 1, in <module>
    interpolate_values(A.astype(object))
  File "<ipython-input-269-b3e686c021f8>", line 9, in interpolate_values
    A[pd.isna(A)] = np.interp(x, xp, fp)
  File "<__array_function__ internals>", line 5, in interp
  File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 1428, in interp
    return interp_func(x, xp, fp, left, right)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

实际上,转换代码在 . 内部interp_func,但这显然是编译后的代码,因此没有给我们更多关于它试图转换的细节。

我们可以通过添加打印行来获取更多信息:

In [275]: def interpolate_values(A):
     ...:     ''' fills values between pairs of events'''
     ...:     if type(A) ==list :
     ...:         A= np.array(A)
     ...:     ok = ~pd.isna(A)
     ...:     xp = ok.nonzero()[0]
     ...:     fp = A[~pd.isna(A)]
     ...:     x  = pd.isna(A).nonzero()[0]
     ...:     print(repr(x), repr(xp), repr(fp))    # NEW LINE
     ...:     A[pd.isna(A)] = np.interp(x, xp, fp)
     ...:     A = [round(i) for i in A]
     ...:     return A
     ...: 
     ...: 
In [276]: interpolate_values(A)
array([], dtype=int64) array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) array([0., 1., 2., 3., 4., 5., 6., 7., 8., 8.])
Out[276]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 8]

In [277]: interpolate_values(A.astype(object))
array([], dtype=int64) array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 8.0], dtype=object)
....
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

x并且xp是相同的,但fp已更改为objectdtype。它不能对object值进行数值插值;他们需要float


推荐阅读