Один путь может быть первым reindex
ваш фрейм данных df1
со всеми возможными комбинациями списков I
, Q
и Tn
с pd.MultiIndex.from_product
, заполняя пропущенное значение в столбце 'V'с 0. Тогда столбец содержит len(I)*len(Q)*len(T)
элементов.Затем вы можете reshape
values
получить каждую строку, относящуюся к одной комбинации на I
и Q
, такую как:
ar = (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 ]]
Теперь, чтобы выполнить умножение с элементом W
, можно создать внешний продукт ar
с самим собой, но построчнополучить для каждой строки матрицу len(T)*len(T)
.Например, для второй строки:
[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.einsum
с правым индексом: np.einsum('ij,ik->ijk',ar,ar)
.Оба дают одинаковый результат.
Следующий шаг можно выполнить с помощью tensordot
и указать правильное значение axes
.Таким образом, используя ar
и W
в качестве входа, вы делаете:
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
(где 1 - W(t0,t0)
и W(t1,t1)
, 2 - это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
...
Примечание: если вы SURE , то каждый элементT
- хотя бы один раз на последнем уровне df1
, ar
можно получить с помощью unstack
, например ar=df1.unstack(fill_value=0).values
.Но я бы предложил использовать метод reindex
, описанный выше, чтобы предотвратить любую ошибку