使用多索引的二次n项方程

时间:2018-11-22 21:33:02

标签: python numpy dataframe multi-index quadratic

我有两个DF,我想用它们来计算以下内容:

w(ti,ti)*a(ti)^2 + w(tj,tj)*b(sj,tj)^2 + 2*w(si,tj)*a(ti)*b(tj)

以上使用两个术语(a,b)。 w是权重df,其中i和j是与a和b的Tn索引有关的索引和列空间。

设置-编辑动态W

import pandas as pd
import numpy as np

I = ['i'+ str(i) for i in range(4)]
Q = ['q' + str(i) for i in range(5)]
T = ['t' + str(i) for i in range(3)]
n = 100

df1 = pd.DataFrame({'I': [I[np.random.randint(len(I))] for i in range(n)],
                    'Q': [Q[np.random.randint(len(Q))] for i in range(n)],
                    'Tn': [T[np.random.randint(len(T))] for i in range(n)],
                    'V': np.random.rand(n)}).groupby(['I','Q','Tn']).sum()

df1.head(5)
I  Q  Tn  V        
i0 q0 t0  1.626799
      t2  1.725374
   q1 t0  2.155340
      t1  0.479741
      t2  1.039178

w = np.random.randn(len(T),len(T))
w = (w*w.T)/2
np.fill_diagonal(w,1)
W = pd.DataFrame(w, columns = T, index = T)

W
          t0        t1        t2
t0  1.000000  0.029174 -0.045754
t1  0.029174  1.000000  0.233330
t2 -0.045754  0.233330  1.000000

有效地,我想使用df1中的索引Tn对每个I和Q使用上述公式。

以上示例中df1.loc['i0','q0']的最终结果应为:

  W(t0,t0) * V(t0)^2 
+ W(t2,t2) * V(t2)^2
+ 2 * W(t0,t2) * V(t0) * V(t2) 
=     
  1.0 * 1.626799**2 
+ 1.0 * 1.725374**2 
+ (-0.045754) * 1.626799 * 1.725374

以上示例中df1.loc['i0','q1']的最终结果应为:

  W(t0,t0) * V(t0)^2 
+ W(t1,t1) * V(t1)^2
+ W(t2,t2) * V(t2)^2
+ 2 * W(t0,t1) * V(t0) * V(t1)
+ 2 * W(t0,t2) * V(t0) * V(t2)
+ 2 * W(t2,t1) * V(t1) * V(t2)
=     
  1.0 * 2.155340**2 
+ 1.0 * 0.479741**2
+ 1.0 * 1.039178**2
+ 0.029174 * 2.155340 * 0.479741 * 1
+ (-0.045754) * 2.155340 * 1.039178 * 1
+ 0.233330 * 0.479741 * 1.039178 * 1

此模式将根据每个Q中的tn项的数量重复,因此它应足够健壮以处理所需的Tn项(在本示例中,我使用3,但可能多达100个或更多)

然后,每个结果应使用Index = [I, Q]保存到新的DF中 当n的价值增加时,解决方案也不应比excel慢。

预先感谢

1 个答案:

答案 0 :(得分:1)

一种方法可能是首先将数据reindex与列表df1IQ的所有可能组合与{{1} },用0填充“ V”列中的缺失值。该列中有Tn个元素。然后,您可以pd.MultiIndex.from_product len(I)*len(Q)*len(T)来获取与reshapevalues上的一个组合相关的每一行,例如:

I

要查看我的输入Qar = (df1.reindex(pd.MultiIndex.from_product([I,Q,T], names=['I','Q','Tn']),fill_value=0) .values.reshape(-1,len(T))) 之间的关系,下面是一些相关的行

df1

现在,要与ar的元素进行乘法,一种方法是创建print (df1.head(6)) V I Q Tn i0 q0 t1 1.123666 q1 t0 0.538610 t1 2.943206 q2 t0 0.570990 t1 0.617524 t2 1.413926 print (ar[:3]) [[0. 1.1236656 0. ] [0.53861027 2.94320574 0. ] [0.57099049 0.61752408 1.4139263 ]] 与其自身的外乘积,但按行逐行获取,每行得到一个{{1} }矩阵。例如,对于第二行:

W

成为

ar

可能有几种方法,例如带有正确下标len(T)*len(T)的{​​{1}}或[0.53861027 2.94320574 0. ] 。两者给出相同的结果。

下一步可以使用[[0.29010102, 1.58524083, 0. ], #0.29010102 = 0.53861027**2, 1.58524083 = 0.53861027*2.94320574 ... [1.58524083, 8.66246003, 0. ], [0. , 0. , 0. ]] 并指定正确的ar[:,:,None]*ar[:,None,:]。因此,以np.einsumnp.einsum('ij,ik->ijk',ar,ar)作为输入,您可以这样做:

tensordot

要在此处检查第二个值,axes(其中1是arW,2是print (np.tensordot(np.einsum('ij,ik->ijk',ar,ar),W.values,axes=([1,2],[0,1]))) array([ 1.26262437, 15.29352438, 15.94605435, ...

最后,要按预期创建数据框,请再次使用1*0.29010102 + 1*8.66246003 + 2.*2*1.58524083 == 15.29352438

W(t0,t0)

请注意:如果您确定,请确保W(t1,t1)的每个元素在W(t0,t1)的最后一级中至少一次,则可以使用以下方法获取pd.MultiIndex.from_product new_df = pd.DataFrame({'col1': np.tensordot(np.einsum('ij,ik->ijk',ar,ar), W.values,axes=([1,2],[0,1]))}, index=pd.MultiIndex.from_product([I,Q], names=['I','Q'])) print (new_df.head(3)) col1 I Q i0 q0 1.262624 q1 15.293524 q2 15.946054 ... ,例如T。但是我建议使用上面的df1方法来防止任何错误