首页 > 解决方案 > pandas 将函数应用于行:只有整数标量数组可以转换为标量索引

问题描述

我有一个df,代码在这里:

df4s = """
    contract  RB  BeginDate  ValIssueDate   EndDate   Valindex0
2  A00118  46   19850100      19880901  99999999          50
3  A00118  47   19000100      19880901  19831231          47
5  A00118  47   19850100      19880901  99999999          50
6  A00253  48   19000100      19820101  19811231          47
7  A00253  48   19820100      19820101  19841299          47
8  A00253  48   19850100      19820101  99999999          50
9  A00253  50   19000100      19820101  19781231          47
10 A00253  50   19790100      19820101  19841299          47
11 A00253  50   19850100      19820101  99999999          50

"""
df4 = pd.read_csv(StringIO(df4s.strip()), sep='\s+', 
                  dtype={"RB": str, "BeginDate": int, "EndDate": int,'ValIssueDate':int,'Valindex0':int})

输出:

contract    RB  BeginDate   ValIssueDate    EndDate Valindex0
2   A00118  46  19850100    19880901    99999999    50
3   A00118  47  19000100    19880901    19831231    47
5   A00118  47  19850100    19880901    99999999    50
6   A00253  48  19000100    19820101    19811231    47
7   A00253  48  19820100    19820101    19841299    47
8   A00253  48  19850100    19820101    99999999    50
9   A00253  50  19000100    19820101    19781231    47
10  A00253  50  19790100    19820101    19841299    47
11  A00253  50  19850100    19820101    99999999    50

我想添加一个新列:

df4['n']

基于现有列之一 df4['RB'] 像这样:

def test(RB):
    n=1
    for i in range(RB,50):
        n+=1
    return n

df4['n']=test(df4['RB'].values)

但是我使用这种 numpy 方式收到错误:

<ipython-input-18-3831e3b8068d> in test(RB)
     17 def test(RB):
     18     n=1
---> 19     for i in range(RB,50):
     20         n+=1
     21     return n

TypeError: only integer scalar arrays can be converted to a scalar index

因为如果我在测试函数中打印 RB 值不是单个值,它是一个数组:

['46' '47' '47' '48' '48' '48' '50' '50' '50'] 

但是,如果我使用较慢的方法,它会起作用:

def test(row):
    n=1
    for i in range(int(row['RB']),50):
        n+=1

df4['n'] = df4.apply(lambda row: test(row), axis=1)

正确的输出是:

contract    RB  BeginDate   ValIssueDate    EndDate Valindex0   n
2   A00118  46  19850100    19880901    99999999    50          5
3   A00118  47  19000100    19880901    19831231    47          4
5   A00118  47  19850100    19880901    99999999    50          4
6   A00253  48  19000100    19820101    19811231    47          3
7   A00253  48  19820100    19820101    19841299    47          3
8   A00253  48  19850100    19820101    99999999    50          3
9   A00253  50  19000100    19820101    19781231    47          1
10  A00253  50  19790100    19820101    19841299    47          1
11  A00253  50  19850100    19820101    99999999    50          1

我想使用更快的方法,而不是更慢的方法,有什么方法可以修复第一种方法吗?目标是在方法 1 中使用循环。

这只是一个示例,我的确切功能非常复杂,它看起来像:

def getnpx(df, age, interest):
    val = 1
    initval = 1
    print(age.astype(int))
    for i in np.arange(age.astype(int), 136):
        val = val * df[str(i)].values
        intval = val / (1 + interest) ** (i + 1 - age)
        initval = initval + intval
    return initval

标签: pythonpandasdataframenumpynumpy-ndarray

解决方案


我终于找到了如何做到这一点的方法:

vfunc=np.vectorize(test)
df4['n']=vfunc(df4['RB'].values)

推荐阅读