在数据帧上乘向量-向量化

时间:2018-11-26 09:49:38

标签: python pandas numpy dataframe

我有一个大小为2441x1441(A)的熊猫数据框,在上三角形中为零-诊断具有值。我想将其每一列乘以长度为2441(B)的向量。棘手的部分是,我想要A的第一个非零值乘以B的第一个值(以及A的第二个值与B的第二个值,依此类推)。这应该在A的所有列上发生,并导致另一个数据帧C。

A=pd.DataFrame(
[[1, 0, 0],
[3, 4, 0],
[6, 7, 8]])

B=np.array([1,2,3,4]).T

结果将是

C=[ 1,  0, 0,
    6,  4, 0,
   18, 14, 8]

我创建了一个for循环,可以在其中循环访问每个值

for x in range(0,len(B)):
    C = (A.iloc[192+x:,:].T*B[0:len(B)-x]).T

但是,这非常慢,我需要在不同的数据集上多次重复此操作。有没有一种很好的,Python化的向量化方法?

3 个答案:

答案 0 :(得分:1)

好的,那么如何从您的B向量创建一个与您想要的形状匹配的数组呢? 以这种方式对其进行转换后,可以执行逐元素乘法,所有正确的值都将对齐。

A = np.array([[1, 0, 0],
              [3, 4, 0],
              [6, 7, 8]])
B = np.array([1,2,3,4])

mB = B[:A.shape[0]]
shift = B[:A.shape[0]]
for b in range(0,A.shape[0]):
    shift = np.roll(shift ,1)
    mB = np.append(mB, shift)
mB.resize(A.shape)
np.tril(mB.T)

>>>> array([[1, 0, 0],
            [2, 1, 0],
            [3, 2, 1]])

在上面,我强制右上角的三角形为零,但是由于您的A向量在那些位置已经为零,所以在乘法数组的这些位置中将要具有的值并不重要-因此,np.tril步骤并不是必需的。

无论如何,无论您的偏好如何,一旦有了该表格(可能比上面使用的方法更好的方式来获得该表格),那么您就可以np.multiply这两个对象相乘了对齐的元素。

np.multiply(A, np.tril(mB.T))

>>>> array([[ 1,  0,  0],
            [ 6,  4,  0],
            [18, 14,  8]])

答案 1 :(得分:1)

这是一种方法:

您可以从B创建下三角矩阵,方法是在每一列上对向量B进行修整和零填充,使其上三角部分全为零。

因此,从本质上讲,您是在复制矩阵乘法运算。然后,您只需使用A*new_Bnp.multiply(A,new_B)将两个矩阵逐个元素相乘即可。

new_b = np.array([list(np.pad(B[:-i] if i != 0 else B,(i,0), 'constant')) 
                  for i in range(len(B))]).T[:len(A),:len(A)]

print(new_b)
array([[1, 0, 0],
       [2, 1, 0],
       [3, 2, 1]])

print(new_b*A)
array([[ 1,  0,  0],
       [ 6,  4,  0],
       [18, 14,  8]])

答案 2 :(得分:1)

使用np.fromfunction定义一个矩阵,其条目为所需的乘数。例如,如果

A = np.array([[1, 0, 0],
              [3, 4, 0],
              [6, 7, 8]])

然后

B = np.clip(np.fromfunction(lambda i, j: i-j+1, A.shape), 0, None)

会给你

B = np.array([[1, 0, 0],
              [2, 1, 0],
              [3, 2, 1]])

,然后您想要的结果只是AB的元素乘积:

C = A * B

收益

C = np.array([[1,  0,  0],
              [6,  4,  0],
              [18, 14, 8]])

实际上,由于您的A是较低三角形的,因此您可以在np.clip的定义中将呼叫删除到B,并获得相同的C

编辑:我对这个问题有误解。如果OP中的B(由于我已经使用过b,所以我叫它B)不是自然数序列,则可以

 B = np.tril(
         np.fromfunction(
             lambda i, j: b[np.clip((i-j).astype(int), 0, b.shape[0])],
             A.shape))

例如,如果

 b = np.array([2, 3, 1, 4])

那么你会得到

 B = np.array([[2, 0, 0],
               [3, 2, 0],
               [1, 3, 2]])